Почему опция требует явного toList внутри для циклов?
Использование цикла for с простым параметром работает:
scala> for (lst <- Some(List(1,2,3))) yield lst
res68: Option[List[Int]] = Some(List(1, 2, 3))
Но цикл по содержимому опции не выполняется:
scala> for (lst <- Some(List(1,2,3)); x <- lst) yield x
<console>:8: error: type mismatch;
found : List[Int]
required: Option[?]
for (lst <- Some(List(1,2,3)); x <- lst) yield x
^
... если параметр явно не преобразован в список:
scala> for (lst <- Some(List(1,2,3)).toList; x <- lst) yield x
res66: List[Int] = List(1, 2, 3)
Почему требуется явное преобразование списка? Является ли это идиоматическим решением?
Ответы
Ответ 1
for (lst <- Some(List(1,2,3)); x <- lst) yield x
переводится на
Some(List(1,2,3)).flatMap(lst => lst.map(x => x))
Метод flatMap
на Option
ожидает функцию, которая возвращает Option
, но вы передаете функцию, которая возвращает List
, и не имеет никакого неявного преобразования от List
до Option
.
Теперь, если вы сначала конвертируете Option
в список, вместо него будет вызываться метод flatMap
List
, который ожидает функцию, возвращающую List
, что и передается вам.
В этом конкретном случае я считаю, что наиболее идиоматическим решением является
Some(List(1,2,3)).flatten.toList