让我们看一下这段代码:
scala> val a = List(Some(4), None)
a: List[Option[Int]] = List(Some(4), None)
scala> a.flatMap( e=> e)
List[Int] = List(4)
为什么在 List[Option[T]]
上应用带有函数 { e => e }
的 flatMap
会返回 List[T]
删除了 None
元素?
具体来说,其背后的概念推理是什么——它是基于函数式编程中的某些现有理论吗?这种行为在其他函数式语言中常见吗?
这虽然确实有用,但同时确实感觉有点神奇和任意。
编辑:
感谢您的反馈和答复。 我重写了我的问题,以更加强调问题的概念性质。我更感兴趣的是了解其背后的形式概念,而不是 Scala 特定的实现细节。
最佳答案
让我们首先看一下 Scaladoc for Option 的伴生对象。在那里我们看到了隐式转换:
implicit def option2Iterable[A](xo: Option[A]): Iterable[A]
这意味着任何选项都可以隐式转换为 Iterable,从而生成包含零个或一个元素的集合。如果您有一个需要 Iterable[A]
的 Option[A]
,编译器将为您添加转换。
在您的示例中:
val a = List(Some(4), None)
a.flatMap(e => e)
我们正在调用List.flatMap
,它采用函数A => GenTraversableOnce[B]
。在这种情况下,A
是 Option[Int]
,B
将被推断为 Int
,因为通过魔法隐式转换时,e
在该函数中返回时将从 Option[Int]
转换为 Iterable[Int]
(这是一个GenTraversableOnce
的子类型)。
此时,我们基本上完成了以下操作:
List(List(1), Nil).flatMap(e => e)
或者,使我们的隐式显式化:
List(Option(1), None).flatMap(e => e.toList)
flatMap
然后适用于 Option,就像适用于 Scala 中的任何线性集合一样:采用 A => List[B]
的函数(再次简化)并生成List[B]
的扁平化集合,取消进程中嵌套集合的嵌套。
关于scala - flatMap 应用于 List[Option[T]] 时的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29214127/