Prof。Odersky在Coursera课程中使用for循环实现了flatMap
,如下所示:
def flatMap[T, U](xs: List[T], f: T => Iterable[U]) = for (x <- xs; y <- f(x)) yield y
下面是两个函数的一些应用(结果如预期(:
val xs = List(1, 2, 3, 4, 5)
flatMap[Int, Int](xs, x=> List(x /2))
然而,当我尝试将flatMap实现为:
for (x <- xs) yield f(x)
它不返回正确的答案,它返回一个列表列表(它应该返回一个包含内部列表所有元素的大列表(
我的问题是,flatMap
能按预期工作的区别是什么;两者之间:
for (x <- xs; y <- f(x)) yield y
//And
for (x <- xs) yield f(x)
为什么for (x <- xs; y <- x * x) yield y
不编译?
您的第二个版本根本不涉及对flatMap的调用。你可以使用具体化去糖的理解和看到:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> val f: Int => Iterable[Int] = null
f: Int => Iterable[Int] = null
scala> val xs = List(1, 2, 3, 4, 5)
xs: List[Int] = List(1, 2, 3, 4, 5)
scala> reify { for (x <- xs; y <- f(x)) yield y }
res0: reflect.runtime.universe.Expr[List[Int]] = Expr[List[Int]]($read.xs.flatMap(((x) => $read.f.apply(x).map(((y) => y))(Iterable.canBuildFrom)))(List.canBuildFrom))
scala> reify { for (x <- xs) yield f(x) }
res1: reflect.runtime.universe.Expr[List[Iterable[Int]]] = Expr[List[scala.Iterable[Int]]]($read.xs.map(((x) => $read.f.apply(x)))(List.canBuildFrom))
第一个可以简化为:
xs.flatMap(x => f(x).map(identity))
相当于:
xs.flatMap(f)
第二个可以简化为:
xs.map(f)