Scala - Option 上的 Map2 函数 --> flatMap vs. Map vs. For-Comprehension
Scala - Map2 function on Option --> flatMap vs. Map vs. For-Comprehension
Option在Scala中是用来处理偏向性的,但是我们也可以将普通的函数提升到Options的上下文中来处理错误。在实现函数 map2 时,我很好奇如何知道何时使用哪些函数。考虑以下实现:
def map2[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C): Option[C] =
ao flatMap {aa =>
bo map {bb =>
f(aa, bb)
aa 是 A 类型,bb 是 B 类型,然后将其馈送到 F,给我们一个 C。但是,如果我们执行以下操作:
def map2_1[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C): Option[C] =
ao flatMap {aa =>
bo flatMap {bb =>
f(aa, bb)
aa 仍然是 A 类型,bb 仍然是 B 类型,但我们必须将最后一次调用包装在 Some(f(aa, bb)) 中以获得 Option[C] 而不是一个普通的C。这是为什么?在这里压平BO是什么意思?
最后但同样重要的是,可以做更简单的事情:
def map2_2[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C): Option[C] = for {
as <- ao
bs <- bo
} yield(f(as,bs))
我知道 for-comprehensions 是 ForEach、maps 和 flatmaps 等的语法糖,但作为开发人员,我如何知道编译器会选择带有 bs <- bo 的 MAP,而不是 flatMap?
我想我即将理解其中的区别,但嵌套的平面图让我感到困惑。
先回答最后一个问题,开发人员知道编译器将如何处理 for
,因为行为是已定义且可预测的:除最后一个外,所有 <-
都变成 flatMap
这将是 map
或 foreach
取决于是否有 yield
.
更广泛的问题似乎是关于 map
和 flatMap
之间的区别。从签名中应该可以清楚地看出区别,例如对于 List
这些是(简化的)签名:
def map[B] (f: A => B) : List[B]
def flatMap[B](f: A => List[B]): List[B]
所以 map
只是将 List
中的值替换为新值,方法是将 f
应用于 A
类型的每个元素以生成 B
.
flatMap
通过连接对原始 List
的每个元素调用 f
的结果生成一个新列表。它相当于 map
后跟 flatten
(因此得名)。
直觉上,map
是 one-for-one 替换,而 flatMap
允许原始 List
中的每个元素生成 0 个或更多新元素。
Option在Scala中是用来处理偏向性的,但是我们也可以将普通的函数提升到Options的上下文中来处理错误。在实现函数 map2 时,我很好奇如何知道何时使用哪些函数。考虑以下实现:
def map2[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C): Option[C] =
ao flatMap {aa =>
bo map {bb =>
f(aa, bb)
aa 是 A 类型,bb 是 B 类型,然后将其馈送到 F,给我们一个 C。但是,如果我们执行以下操作:
def map2_1[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C): Option[C] =
ao flatMap {aa =>
bo flatMap {bb =>
f(aa, bb)
aa 仍然是 A 类型,bb 仍然是 B 类型,但我们必须将最后一次调用包装在 Some(f(aa, bb)) 中以获得 Option[C] 而不是一个普通的C。这是为什么?在这里压平BO是什么意思?
最后但同样重要的是,可以做更简单的事情:
def map2_2[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C): Option[C] = for {
as <- ao
bs <- bo
} yield(f(as,bs))
我知道 for-comprehensions 是 ForEach、maps 和 flatmaps 等的语法糖,但作为开发人员,我如何知道编译器会选择带有 bs <- bo 的 MAP,而不是 flatMap?
我想我即将理解其中的区别,但嵌套的平面图让我感到困惑。
先回答最后一个问题,开发人员知道编译器将如何处理 for
,因为行为是已定义且可预测的:除最后一个外,所有 <-
都变成 flatMap
这将是 map
或 foreach
取决于是否有 yield
.
更广泛的问题似乎是关于 map
和 flatMap
之间的区别。从签名中应该可以清楚地看出区别,例如对于 List
这些是(简化的)签名:
def map[B] (f: A => B) : List[B]
def flatMap[B](f: A => List[B]): List[B]
所以 map
只是将 List
中的值替换为新值,方法是将 f
应用于 A
类型的每个元素以生成 B
.
flatMap
通过连接对原始 List
的每个元素调用 f
的结果生成一个新列表。它相当于 map
后跟 flatten
(因此得名)。
直觉上,map
是 one-for-one 替换,而 flatMap
允许原始 List
中的每个元素生成 0 个或更多新元素。