Scala 中的惰性计算、thunk 和函数闭包

Lazy evaluation, thunk and function closure in Scala

提问人:Rupam Bhattacharjee 提问时间:3/13/2020 最后编辑:Mario GalicRupam Bhattacharjee 更新时间:3/13/2020 访问量:307

问:

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 是一个 case 类,它将类型的对象作为构造函数参数。Function0[A]

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

test2还使用非严格参数并返回 的实例。 创建时,它将获得 .未计算,绑定到调用方 - 。当应用于创建时,通过 ,得到计算(从而打印 hello) 然后缓存结果,即 .对 while creating 的后续调用使用计算值。然而,由于它不是本地的,所以这一切的唯一方法就是通过闭包。Test[Int]b1elem = () => yytest2elemb2elem()y1elem()b3yelem

这准确吗?

注意:我已经浏览了这里发布的示例:Scala 惰性评估和应用函数,但这并不是我想要理解的

Scala 闭包 lazy-evaluation thunk

评论


答:

2赞 som-snytt 3/13/2020 #1

您可以使用 查看捕获元素的实现。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))
      })
    };

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