下面的结果是Intellij IDEA Scala Worksheet内的ALL,但标准的scala REPL似乎是一致的,因此这可能是由于工作表的包装。
scala益智游戏网站上有一个谜题here。
object XY {
object X {
val value: Int = Y.value + 1
}
object Y {
val value: Int = X.value + 1
}
}
println(if (math.random > 0.5) XY.X.value else XY.Y.value)
上面提到的正确答案是2(对于scala 2.10.0?)。但是在Intellij工作表(scala 2.11.7)中,它会发出stackoverflowError。
另外,如spec
中所述对象定义定义符合模板tt的单个对象(或:模块)。它大致相当于以下懒惰值的定义
下面也会给出stackoverflowError。
lazy val x: Int = y + 1
lazy val y: Int = x + 1
以下是其他一些观察结果。
object XXX {
val x: Int = y + 1
lazy val y: Int = x + 1
}
s"XXX x=${XXX.x} y=${XXX.y}"
// XXX x=2 y=1
val x: Int = y + 1
s"plain x=$x"
lazy val y: Int = x + 1
s"plain y=$y"
// stackoverflowError
object XXX {
val x: Int = y + 1
lazy val y: Int = x + 1
}
s"XXX x=${XXX.x} y=${XXX.y}"
val x: Int = y + 1
s"plain x=$x"
lazy val y: Int = x + 1
s"plain y=$y"
// XXX x=2 y=1
// NO output any longer for subsequent scripts
它是一个已知的Intellij scala插件错误吗?
答案 0 :(得分:1)
在Scala 2.11.8上我没有错误,我猜这与你设置中的其他内容有关。你给出的链接给出了一个非常好的解释,为什么它的工作原理 - 它基本上归结为JVM初始化魔术,具体来说:
VM注意到对象X的初始化已经存在 运行并返回X.value的当前值,该值为零( Int字段的默认值),因此在运行时没有堆栈溢出。
然而,这种魔法也没有理由适用于
lazy val x: Int = y + 1
lazy val y: Int = x + 1
正确的是堆栈溢出。
这里没有任何意外 - 这只是初始化前字段默认值为0的常见情况。在初始化x
期间(首先发生),y
的初始化被触发,它使用当前值x
(默认为0
,因为{{1}尚未初始化)并计算x
。然后,我们返回初始化y = 0 + 1 = 1
,并计算x
。
这有点难看,因为这段代码需要在一些东西里面编译(一个对象,一个类,一个函数,一个方法,SOMETHING!)。在类或对象内部,上面的推理适用(这是Scala REPL中发生的事情,因为它基本上只是在对象内部运行裸代码)。
另一方面,如果你把它放在一个函数或方法中,它根本就不应该编译,因为你有一个前向引用。它应该失败,例如:
x = 1 + 1 = 2
我说Intellij IDEA Scala工作表没有正确处理。
我无法对此发表任何言论。在之前的案例中,我已经覆盖了预期的Scala输出 - 这完全取决于代码的包装方式(在对象/类或方法/函数中)。同样,Intellij IDEA Scala工作表似乎无法正常工作。