There is a question asking about the implementation of lazy val
s if they're class variables. How are implemented local variables, such in
def foo[A](a: => A) = {
lazy val x: A = a
// return something that uses x
}
It's a bit less efficient to use lazy vals in a method. The reason is that you can't actually nest functions so the lazy bits which nominally are allocated on the stack actually need to go on the heap. So you have to create at least one extra object, and it turns out that Scala actually creates two.
class Baz{
def baz(i: => Int, b: Boolean) = {
lazy val j = i
if (b) j else 0
}
}
turns into, among other things
public int baz(scala.Function0, boolean);
Code:
0: new #12; //class scala/runtime/IntRef
3: dup
4: iconst_0
5: invokespecial #16; //Method scala/runtime/IntRef."<init>":(I)V
8: astore_3
9: new #18; //class scala/runtime/VolatileByteRef
12: dup
13: iconst_0
14: invokespecial #21; //Method scala/runtime/VolatileByteRef."<init>":(B)V
17: astore 4
19: iload_2
20: ifeq 34
23: aload_0
24: aload_1
25: aload_3
26: aload 4
28: invokespecial #25; //Method j$1:(Lscala/Function0;Lscala/runtime/IntRef;
Lscala/runtime/VolatileByteRef;)I
31: goto 35
34: iconst_0
35: ireturn
See the creation of IntRef
and VolatileByteRef
? These are in place of what would normally be just private vars to handle the lazy val. And now j$1
, the accessor method created to handle retrieval and/or creation of the lazy val, has to take those two newly created classes as parameters (in addition to the by-name function).
So while the underlying mechanics are the same, the implementation details are different and less efficient than if you already had another class around in which to stick the vars.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With