这不起作用:
val res = myOption flatMap (value => Seq(value, “blo”))
但是这是的:
val res = myOption.toSeq flatMap (value => Seq(value, “blo”))
您认为flatMap
上的Option
应该像GenTraversableOnce
一样Seq
吗?
或者此代码对可读性不利,我应该使用match
或map
/ getOrElse
?
修改:我们在for
/ yield
上也遇到了同样的问题。
干杯
答案 0 :(得分:3)
Option.flatMap
返回Option
,它与序列“相似”,但不能包含多个元素。如果允许使用函数,则返回Seq
,并返回包含多个元素的Seq
,flatMap
的返回值是什么(请记住,它需要成为Option
)?
为什么flatMap
首先需要返回一个选项?好吧,所有 flatMap
实现返回与它们开始时相同的类型。这是有道理的:如果我有一个Option
的东西,并想以某种方式转换内容,最常见的用例是我想最终得到另一个Option
。如果flatMap
给我一个Seq
,我会这样做吗? .headOption
?这不是一个好主意,因为它可能会默默地丢弃数据。 if(seq.size < 2) seq.headOption else throw ....
?嗯,这有点好,但看起来很难看,并且在编译时不可执行。
另一方面,当您需要时将Option
转换为Seq
非常简单且完全安全:只需执行.toSeq
。
答案 1 :(得分:3)
flatMap
的整体语义是像monadic bind
方法一样工作,这意味着它往往具有类似
[A]this:T[A].flatMap[B](f: A => T[B]): T[B]
有时候(SeqLike
)此签名被推广到
[A]this:T[A].flatMap[B](f: A => F[B]): T[B]
其中F[B]
可轻松转换为T[B]
因此,不仅Option
,而且concurrent.Future
,util.Try
和BindOps
- scalaz monads的扩展语法具有不接受任何可遍历的方法flatMap
,但只有相同的包装类型。
即。 flatMap
更多来自monads世界,而不是来自集合