首页 > 解决方案 > Scala 中的惰性求值、thunk 和函数闭包

问题描述

case class Test[A](elem: () => A)

object Fun extends App {

  def test1(v: => Int): Test[Int] = Test(() => v)

  val a1 = test1({ println("hello"); 1 })
  val a2 = a1.elem() //echoes hello
  val a3 = a1.elem() //echoes hello

  def test2(v: => Int): Test[Int] = {
    lazy val y = v
    Test(() => y)
  }

  val b1 = test2({ println("hello"); 1 })
  val b2 = b1.elem() //echoes hello
  val b3 = b1.elem() //doesn't echo hello. Is function closure at work here?
}

Test 是一个将类型对象Function0[A]作为构造函数参数的案例类。

test1使用非严格参数并返回Test[Int]. 创建时a1,它得到elem = () => { println("hello"); 1 }. 因此,当hello被打印两次a2a3通过应用 elem 创建时,这是有意义的。

test2还使用非严格参数并返回Test[Int]. 创建时b1,它得到elem = () => y. 未y评估并绑定到调用者 - test2。Whenelem应用于 create b2, through elem()y被评估(并因此打印hello),然后缓存结果为1. elem()创建时的后续调用b3使用评估值。但是,由于y不是本地的elem,所有这些都可以工作的唯一方法是通过关闭。

那准确吗?

注意:我已经浏览了此处发布的示例:Scalalazy evaluation and apply function,但这并不是我想要理解的

标签: scalaclosureslazy-evaluationthunk

解决方案


您可以使用scalac -Vprint:_.

在这种情况下,

    def test2(v: Function0): Test = {
      lazy <artifact> val y$lzy: scala.runtime.LazyInt = new scala.runtime.LazyInt();
      new Test({
        (() => Fun.this.$anonfun$test2$1(y$lzy, v))
      })
    };

惰性局部变为堆分配的,引用传递到闭包中。


推荐阅读