简体   繁体   English

在scala Intellij工作表中彼此依赖的两个val的初始化?

[英]initialization of two vals depending on each other in scala Intellij worksheet?

The results below are ALL within Intellij IDEA Scala Worksheet but standard scala REPL seems consistent therefore this might due to the wrapping of the worksheet . 下面的结果在Intellij IDEA Scala工作表中是全部,但是标准的scala REPL似乎是一致的,因此,这可能是由于工作表的包装所致

There is a puzzle here on scala puzzlers site. 有一个谜这里上阶困惑的网站。

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)

The mentioned correct answer is 2 (for scala 2.10.0?). 提到的正确答案是2(对于scala 2.10.0?)。 However inside Intellij worksheet (scala 2.11.7) it emits a stackoverflowError. 但是,在Intellij工作表(scala 2.11.7)中,它发出stackoverflowError。

Also, as mentioned in the spec 另外,如规格中所述

The object definition defines a single object (or: module) conforming to the template tt. 对象定义定义符合模板tt的单个对象(或:模块)。 It is roughly equivalent to the following definition of a lazy value 它大致等效于以下对惰性值的定义

Indeed below would also give a stackoverflowError. 实际上,下面还会给出一个stackoverflowError。

lazy val x: Int = y + 1
lazy val y: Int = x + 1

Here are a few other observations. 这是其他一些观察结果。

Case 1 情况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

Case 2 情况二

val x: Int = y + 1
s"plain x=$x"
lazy val y: Int = x + 1
s"plain y=$y"
// stackoverflowError

Case 3 情况3

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

Is it a known Intellij scala plugin bug? 这是一个已知的Intellij scala插件错误吗?

On Scala 2.11.8 I get no error, I'm going to guess this is related to something else in your setup. 在Scala 2.11.8上,我没有收到任何错误,我想这可能与您的设置中的其他内容有关。 The link you gave gives a pretty good explanation why this works - it basically boils down to JVM initialization magic, specifically: 您提供的链接很好地解释了为什么该方法有效-基本上可以归结为JVM初始化的魔力,特别是:

The VM takes notice that the initialization of object X is already running and returns the current value of X.value which is zero (the default value for Int fields), so no stack overflow at runtime. VM注意到对象X的初始化已在运行,并返回X.value的当前值,该值为零(Int字段的默认值),因此在运行时不会出现堆栈溢出。

Yet there is no reason for this magic to also apply to 然而,没有理由将这种魔力也适用于

lazy val x: Int = y + 1
lazy val y: Int = x + 1

which rightly is a stack overflow. 正确的是堆栈溢出。

Case 1 情况1

Here there are no surprises - this is just the usual case of the default value of fields being 0 before initialization. 这里没有什么奇怪的-这只是初始化之前字段默认值为0的通常情况。 During the initialization of x (which happens first), the initialization of y is triggered and it uses the current value of x (which defaults to 0 since x hasn't been initialized yet) and calculates y = 0 + 1 = 1 . x的初始化期间(首先发生),触发y的初始化,并使用x的当前值(由于x尚未初始化,因此默认为0 )并计算y = 0 + 1 = 1 Then, we return to initializing x , and calculate x = 1 + 1 = 2 . 然后,返回初始化x ,并计算x = 1 + 1 = 2

Case 2 情况二

This is a bit ugly because this code needs to be inside of something to compile (an object, a class, a function, a method, SOMETHING!). 这有点丑陋,因为此代码必须在要编译的东西(对象,类,函数,方法,某些东西!)内部。 Inside a class or an object, the reasoning above applies (and this is what happens in the Scala REPL since it basically just runs bare code inside of objects). 在类或对象内部,上面的推理适用(这就是Scala REPL中发生的事情,因为它基本上只在对象内部运行裸代码)。

On the other hand, if you put this in a function or method it shouldn't compile at all, since you have a forward reference. 另一方面,如果将其放在函数或方法中,则根本不应该编译,因为您具有前向引用。 It should fail with something like: 它应该失败,并显示类似以下内容:

error: forward reference extends over definition of value x
   val x: Int = y + 1
                ^

I'd say Intellij IDEA Scala Worksheet is not handling this properly. 我会说Intellij IDEA Scala工作表无法正确处理。

Case 3 情况3

I can't say anything about this. 我对此无话可说。 I've covered the expected Scala outputs for this in the previous cases - this all depends on how the code is being wrapped (in an object/class or method/function). 在之前的案例中,我已经介绍了预期的Scala输出-所有这些都取决于代码的包装方式(在对象/类或方法/函数中)。 Again, Intellij IDEA Scala Worksheet seems to not be working. 同样,Intellij IDEA Scala工作表似乎不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM