Scala 的惰性验证的(隐藏)成本是多少?展示了它们是如何在 Scala 2.7 中实现的。但正如评论所说,从那时起这一定已经改变了,所以我很好奇,类lazy val
变量的当前(2.10)实现是什么?
问问题
2096 次
2 回答
24
用 scala 2.10.2 编译:
class Foo {
lazy val bar = math.pow(5, 3)
}
然后用JD-GUI反编译结果:
import scala.math.package.;
import scala.reflect.ScalaSignature;
@ScalaSignature(bytes="\006\001e1A!\001\002\001\013\t\031ai\\8\013\003\r\tq\001P3naRLhh\001\001\024\005\0011\001CA\004\013\033\005A!\"A\005\002\013M\034\027\r\\1\n\005-A!AB!osJ+g\rC\003\016\001\021\005a\"\001\004=S:LGO\020\013\002\037A\021\001\003A\007\002\005!A!\003\001EC\002\023\0051#A\002cCJ,\022\001\006\t\003\017UI!A\006\005\003\r\021{WO\0317f\021!A\002\001#A!B\023!\022\001\0022be\002\002")
public class Foo {
private double bar;
private volatile boolean bitmap$0;
private double bar$lzycompute() {
synchronized (this) {
if (!this.bitmap$0) {
this.bar = package..MODULE$.pow(5.0D, 3.0D);
this.bitmap$0 = true;
}
return this.bar;
}
}
public double bar() {
return this.bitmap$0 ? this.bar : bar$lzycompute();
}
}
编辑- 这是三个字段的样子:
class Foo {
lazy val a = math.pow(5, 1)
lazy val b = math.pow(5, 2)
lazy val c = math.pow(5, 3)
}
反编译:
import scala.math.package.;
import scala.reflect.ScalaSignature;
@ScalaSignature(bytes="\006\001\0052A!\001\002\001\013\t\031ai\\8\013\003\r\tq\001P3naRLhh\001\001\024\005\0011\001CA\004\013\033\005A!\"A\005\002\013M\034\027\r\\1\n\005-A!AB!osJ+g\rC\003\016\001\021\005a\"\001\004=S:LGO\020\013\002\037A\021\001\003A\007\002\005!A!\003\001EC\002\023\0051#A\001b+\005!\002CA\004\026\023\t1\002B\001\004E_V\024G.\032\005\t1\001A\t\021)Q\005)\005\021\021\r\t\005\t5\001A)\031!C\001'\005\t!\r\003\005\035\001!\005\t\025)\003\025\003\t\021\007\005\003\005\037\001!\025\r\021\"\001\024\003\005\031\007\002\003\021\001\021\003\005\013\025\002\013\002\005\r\004\003")
public class Foo {
private double a;
private double b;
private double c;
private volatile byte bitmap$0;
private double a$lzycompute() {
synchronized (this) {
if ((byte)(this.bitmap$0 & 0x1) == 0) {
this.a = package..MODULE$.pow(5.0D, 1.0D);
this.bitmap$0 = ((byte)(this.bitmap$0 | 0x1));
}
return this.a;
}
}
private double b$lzycompute() {
synchronized (this) {
if ((byte)(this.bitmap$0 & 0x2) == 0) {
this.b = package..MODULE$.pow(5.0D, 2.0D);
this.bitmap$0 = ((byte)(this.bitmap$0 | 0x2));
}
return this.b;
}
}
private double c$lzycompute() {
synchronized (this) {
if ((byte)(this.bitmap$0 & 0x4) == 0) {
this.c = package..MODULE$.pow(5.0D, 3.0D);
this.bitmap$0 = ((byte)(this.bitmap$0 | 0x4));
}
return this.c;
}
}
public double a() {
return (byte)(this.bitmap$0 & 0x1) == 0 ? a$lzycompute() : this.a;
}
public double b() {
return (byte)(this.bitmap$0 & 0x2) == 0 ? b$lzycompute() : this.b;
}
public double c() {
return (byte)(this.bitmap$0 & 0x4) == 0 ? c$lzycompute() : this.c;
}
}
于 2013-07-14T18:42:23.880 回答
0
更新 Scala 2.12.1(2016 年 12 月,三年后)。
在PR 5294(字段阶段完全扩展惰性 vals 和模块)之后,您可以在提交 743f0d2中阅读:
没有本地的懒惰 val。
现在
synchronized
被特别擦除以避免拳击,我们可以放弃这个工作。请注意,这确实在慢速路径上添加了额外的强制转换和 getter 调用,但这可能并不重要。
class C { def foo = {lazy val x = {println("a"); "A" }; x } }
变成:
def foo(): String = {
lazy <artifact> val x$lzy: scala.runtime.LazyRef[String] = new scala.runtime.LazyRef[String]();
<artifact> private def x$lzycompute(): String =
x$lzy.synchronized[String]{
if (x$lzy.initialized())
x$lzy.value() // NOTE: gets an `.asInstanceOf[String]` after erasure
else
{
x$lzy.value_=({
scala.Predef.println("a");
"A"
});
x$lzy.initialized_=(true);
x$lzy.value() // NOTE: gets an `.asInstanceOf[String]` after erasure
}
}
lazy def x(): String =
if (x$lzy.initialized())
x$lzy.value() // NOTE: gets an `.asInstanceOf[String]` after erasure
else
x$lzycompute();
x()
}
于 2016-12-26T23:02:42.047 回答