用于理解实现flatMap的scala



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)

最新更新