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 is a case class that takes an object of type Function0[A]
as constructor argument.
test1
uses a non-strict parameter and returns an instance of Test[Int]
. when a1
is created, it gets elem = () => { println("hello"); 1 }
elem = () => { println("hello"); 1 }
. And so it makes sense when hello gets printed twice while a2
and a3
are created by applying elem.
test2
also uses a non-strict parameter and returns an instance of Test[Int]
. when b1
is created, it gets elem = () => y
. The y
is unevaluated and is bound to the caller - test2
. When elem
is applied to create b2
, through elem()
, y
gets evaluated (and thus prints hello ) and then caches the result which is 1
. Subsequent call to elem()
while creating b3
uses the evaluated value. However since y
is not local to elem
, the only way all this can work is through closure.
Is that accurate?
Note: I have gone through the example posted here : Scala lazy evaluation and apply function but it isn't exactly what I am trying to understand
You can see the implementation of captured elements using scalac -Vprint:_
.
In this case,
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))
})
};
The lazy local becomes heap-allocated, with a reference passed into the closure.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.