了解如何通过map,flatMap和Filter表示语句

时间:2013-11-09 15:26:37

标签: scala functional-programming

我有以下代码:

val e1 = 10 :: 15 :: 20 :: 25 :: Nil
val e2 = 10 :: 15 :: 20 :: 25 :: Nil

val y = for {
    e <- e1 if(e%2==0)
} yield e

val y1 = e1.withFilter(x => (x%2 == 0)).map(Int=>Int)

val e31 = for{
    i <- e1
    j <- e2 if (isPrime(i+j))
} yield(i,j)

现在您可以看到yy1两个都给了我完全相同的值,这证明我已成功代表for语句(单一生成器+过滤器)with withFilter和地图。

但是当我有一个带有多个生成器和过滤器的for语句时(例如:val e31),我无法找到如何用map,filterMap和withFilter表示它。

2 个答案:

答案 0 :(得分:2)

scala> val e31 = for{
     |     i <- e1
     |     j <- e2
     |     if ((i+j) % 2 == 0)
     |     } yield(i,j)
res1: List[(Int, Int)] = List((10,10), (10,20), (15,15), (15,25), (20,10), (20,20), (25,15), (25,25))


scala> e1.flatMap(i => e2.withFilter(j => ((i+j)%2 == 0)).map(j => (i,j)))
res2: List[(Int, Int)] = List((10,10), (10,20), (15,15), (15,25), (20,10), (20,20), (25,15), (25,25))

请查看this问题,以获得有关每个for-construct如何翻译的更详细答案。

答案 1 :(得分:1)

实际上,有一种方法可以强制Scala编译器向我们展示它如何消除for理解。

例如,在编译此代码时:

object dummy {    
  val e31 = for{
  i <- e1
  j <- e2
  if (isPrime(i+j))
  } yield(i,j)
}

scalac -Xprint:parser dummy.scala,你会得到:

[[syntax trees at end of                    parser]] // dummy.scala
package <empty> {
  object dummy extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    val e31 = e1.flatMap(((i) => e2.withFilter(((j) => isPrime(i.$plus(j)))).map(((j) => scala.Tuple2(i, j)))))
  }
}

代码有错误(各种标识符未定义)但这里没关系,因为parser还没有看到这些错误。