【发布时间】:2018-04-07 02:16:19
【问题描述】:
我为什么会写
val flat: List[Int] = List(Some(1), Some(2)).flatMap(i => i)
但不是
val flat: List[Int] = List(Some(1), Some(2)).flatMap(_)
【问题讨论】:
标签: scala
我为什么会写
val flat: List[Int] = List(Some(1), Some(2)).flatMap(i => i)
但不是
val flat: List[Int] = List(Some(1), Some(2)).flatMap(_)
【问题讨论】:
标签: scala
下划线是变量的占位符。它本身并不是一个函数。 flatMap 需要一个函数。
此外,在这种情况下,List 上定义了一个 flatten 方法,Option 在 Predef 内有一个隐式转换,这样你写的内容就可以浓缩成打电话,List(Some(1)).flatten
【讨论】:
flatten,仅适用于相同的M[_] 或Iterables 和Option。
identity,它在Predef.scala 中定义为def identity[A](x: A): A = x,而flatten 这样的便利不可用。
下划线规则List(Some(1), Some(2)).flatMap(_) 是x => List(Some(1), Some(2)).flatMap(x) 的缩写,而不是List(Some(1), Some(2)).flatMap(x => x)。
【讨论】:
简短的回答是下划线可以指一个身份映射,例如x => x,但是 flatMap 需要映射到TraversableOnce[U],例如项目列表。
例如,List(1, 2).flatMap(Seq(_)) 有效。 List(1, 2).map(_ + 2) 也可以。第一个只是身份映射,第二个将返回List(3, 4)。
但是,如果在map 的flatMap 中有复杂的转换(多个运算符),则必须正确编写 lambda 函数,否则编译器无法正确推断类型。见Scala unexpectedly not being able to ascertain type for expanded function。
【讨论】: