功能没有被懒惰地评估

时间:2014-08-17 13:26:12

标签: scala lazy-evaluation

在下面的代码中,我测试了我对Scala懒惰评估的理解。

我尝试在函数定义中只处理一次集合。但是可以在下面看到processMap被调用多个tiems。它应该只被调用一次吗?

  val a = Array( ("1" , "1") , ("2" , "2"))       //> a  : Array[(String, String)] = Array((1,1), (2,2))

  def toLazyMapDef(aparam : Array[(String, String)]) = {
    lazy val toMap = processMap(aparam)
    toMap
  }                                               //> toLazyMapDef: (aparam: Array[(String, String)])scala.collection.immutable.Ma
                                                  //| p[String,String]
  def processMap(aparam : Array[(String, String)]) = {

    println("in processMap")
    aparam.toMap
  }                                               //> processMap: (aparam: Array[(String, String)])scala.collection.immutable.Map[
                                                  //| String,String]

  println(toLazyMapDef(a))                        //> in processMap
                                                  //| Map(1 -> 1, 2 -> 2)
  println(toLazyMapDef(a))                        //> in processMap
                                                  //| Map(1 -> 1, 2 -> 2)
  println(toLazyMapDef(a))                        //> in processMap
                                                  //| Map(1 -> 1, 2 -> 2)

1 个答案:

答案 0 :(得分:4)

这里,lazy val toMap是函数的内部变量。它不会在函数调用之间保留。这可能是一个更好的例子(我们将lazy val作为类成员,我们可以证明它只被评估一次):

case class LazyMapDemo(aparam : Array[(String, String)]) {
    lazy val toMap = processMap(aparam)
    def giveLazyMap = toMap
    def processMap(aparam : Array[(String, String)]) = {
      println("in processMap")
      aparam.toMap
   }
  }    

scala> val a = Array( ("1" , "1") , ("2" , "2"))
a: Array[(String, String)] = Array((1,1), (2,2))

scala> val ld = LazyMapDemo(a)
ld: LazyMapDemo = LazyMapDemo([Lscala.Tuple2;@63f5faaa)

scala> ld.toMap
in processMap
res0: scala.collection.immutable.Map[String,String] = Map(1 -> 1, 2 -> 2)

scala> ld.toMap // processMap not called
res1: scala.collection.immutable.Map[String,String] = Map(1 -> 1, 2 -> 2)

scala> ld.giveLazyMap // processMap not called
res2: scala.collection.immutable.Map[String,String] = Map(1 -> 1, 2 -> 2)