[英]Lazy evaluation, thunk and function closure in Scala
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
使用非严格参数并返回Test[Int]
的实例。 当a1
创建时,它得到elem = () => { println("hello"); 1 }
elem = () => { println("hello"); 1 }
. 因此,当hello被打印两次而a2
和a3
是通过应用 elem 创建时,这是有道理的。
test2
还使用非严格参数并返回Test[Int]
的实例。 当b1
创建时,它得到elem = () => y
。 y
未计算并且绑定到 caller- test2
。 当elem
用于创建b2
,通过elem()
, y
被评估(并因此打印hello ),然后缓存结果1
。 创建b3
对elem()
后续调用使用评估值。 然而,由于y
不是elem
本地的,所以所有这些都可以工作的唯一方法是通过闭包。
那是准确的吗?
注意:我已经浏览了此处发布的示例: Scala 延迟评估和应用函数,但这并不是我想要理解的内容
您可以使用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))
})
};
惰性本地变为堆分配,并将引用传递到闭包中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.