为什么 "flatMap" 在 Scala 中使用 Option 类型的序列?
Why does "flatMap" work with sequences of Option type in Scala?
我不明白 Scala 编译器是如何计算出如何将 flatMap
与 Option
序列一起使用的。
如果我在序列序列上使用 flatMap
:
println(Seq(Seq(1), Seq()).flatMap(a => a)) // List(1)
它将连接所有嵌套序列
如果我将它与一系列 Option
s:
一起使用,也会发生同样的情况
println(Seq(Some(1), None).flatMap(a => a)) // List(1)
所以在这种情况下 flatMap
将 Option
视为一个集合。问题是为什么这行得通? flatMap
具有以下定义:
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That
意味着它需要一个 returns GenTraversableOnce
实例的函数,但 Option
不会继承 GenTraversableOnce
。它只继承Product
和Serializable
,Product
继承Equals
.
在这种情况下,Scala 编译器如何在 Option
的序列上使用 flatMap
?
你的观察是对的。在这种情况下,如果编译器无法匹配类型,它会寻找隐式转换并在 Option
的伴随对象中找到一个:
import scala.language.implicitConversions
/**
An implicit conversion that converts an option to an iterable value
*/
implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList
这使得将 Option
s 视为 Iterable
s 成为可能。
此外,您的代码可以使用 flatten
来简化:
Seq(Some(1), None).flatten
我不明白 Scala 编译器是如何计算出如何将 flatMap
与 Option
序列一起使用的。
如果我在序列序列上使用 flatMap
:
println(Seq(Seq(1), Seq()).flatMap(a => a)) // List(1)
它将连接所有嵌套序列
如果我将它与一系列 Option
s:
println(Seq(Some(1), None).flatMap(a => a)) // List(1)
所以在这种情况下 flatMap
将 Option
视为一个集合。问题是为什么这行得通? flatMap
具有以下定义:
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That
意味着它需要一个 returns GenTraversableOnce
实例的函数,但 Option
不会继承 GenTraversableOnce
。它只继承Product
和Serializable
,Product
继承Equals
.
在这种情况下,Scala 编译器如何在 Option
的序列上使用 flatMap
?
你的观察是对的。在这种情况下,如果编译器无法匹配类型,它会寻找隐式转换并在 Option
的伴随对象中找到一个:
import scala.language.implicitConversions
/**
An implicit conversion that converts an option to an iterable value
*/
implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList
这使得将 Option
s 视为 Iterable
s 成为可能。
此外,您的代码可以使用 flatten
来简化:
Seq(Some(1), None).flatten