функция flatMap в scala - PullRequest
2 голосов
/ 03 мая 2020

В следующих двух сценариях ios у меня есть функция flatMap, вызываемая в списке. В обоих случаях часть карты функции flatMap возвращает массив с итератором. В первом случае код выдает ошибку, где во втором случае выдает ожидаемый результат.

Сценарий-1

val x = List("abc","cde")
x flatMap ( e => e.toArray)
<console>:13: error: polymorphic expression cannot be instantiated to expected type;
 found   : [B >: Char]Array[B]
 required: scala.collection.GenTraversableOnce[?]
       x flatMap ( e => e.toArray)

Сценарий-2

val x = List("abc,def")
x flatMap ( e => e.split(",") )
res1: List[String] = List(abc, def) //Result

Не могли бы вы помочь, почему в первом случае он не ведет себя так, как ожидалось?

Ответы [ 4 ]

3 голосов
/ 03 мая 2020

Стоит помнить, что Array не является надлежащей коллекцией Scala, поэтому компилятору приходится работать усерднее, чтобы сначала преобразовать ее во что-то, что соответствует остальным Scala коллекциям

implicitly[Array[Char] <:< GenTraversableOnce[Char]] // error (Scala 2.12)
implicitly[Array[Char] <:< IterableOnce[Char]]       // error (Scala 2.13)

Следовательно, поскольку flatMap принимает функцию

String => GenTraversableOnce[Char]

, но мы передаем

String => Array[Char]

, компилятор сначала должен найти соответствующее неявное преобразование Array[Char] в GenTraversableOnce[Char]. А именно, это должно быть wrapCharArray

scala.collection.immutable.List.apply[String]("abc", "cde").flatMap[Char](((e: String) => scala.Predef.wrapCharArray(scala.Predef.augmentString(e).toArray[Char]((ClassTag.Char: scala.reflect.ClassTag[Char])))))

или короче

List("abc", "cde").flatMap(e => wrapCharArray(augmentString(e).toArray))

, однако из-за причин вывода типа, объясненных Jasper-M, компилятор не может выбрать wrapCharArray преобразование. Как говорит Даниэль

Array пытается быть коллекцией Java Array и Scala одновременно. В большинстве случаев это удается, но в некоторых угловых случаях терпит неудачу.

Возможно, это один из тех угловых случаев. По этим причинам лучше избегать Array, если это не обусловлено соображениями производительности или совместимости. Тем не менее, другой подход, который работает в Scala 2.13, заключается в использовании to(Collection) метода

List("abc","cde").flatMap(_.to(Array))
3 голосов
/ 03 мая 2020

Я думаю, что разница в том, что в сценарии 1 у вас на самом деле есть Array[B], где B - некоторый еще не решенный супертип Char. Обычно компилятор ищет неявное преобразование в GenTraversableOnce, но поскольку B еще не известно, вы сталкиваетесь с проблемой / ограничением вывода типов.

Вы можете помочь выводу типа, заполнив B.

List("abc", "cde").flatMap(_.toArray[Char])

Или, что еще лучше, вам не нужно flatMap в этом случае. Просто позвоните flatten.

List("abc", "cde").flatten
0 голосов
/ 03 мая 2020
scala> val x = List("abc","cde")
x: List[String] = List(abc, cde)

scala> x.flatMap[Char](_.toArray)
res0: List[Char] = List(a, b, c, c, d, e)
0 голосов
/ 03 мая 2020

Как говорится в ошибке, ваш тип неверен.

В первом случае, если вы применяете карту, а не плоскую карту, вы получаете List [Array [Char]]. Если вы примените flatten к этому, вы получите List [Char]

Во втором случае, если вы примените карту, а не flatmap, вы получите List [Array [String]]. Если вы примените flatten к этому, вы получите List [String]

Я полагаю, вам нужно преобразовать String в Char в вашем массиве, чтобы заставить его работать.

Я использую Scala 2.13 и по-прежнему имеют ту же ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...