Scala线性化与懒惰的vals,为什么无限递归?

时间:2014-08-12 15:28:30

标签: scala

尝试实现利用Scala线性化的结构,我们发现了一些我们无法理解的行为。

如果将覆盖的字段设置为def,一切都按预期进行,如果我们将其设置为lazy val,它会以无限递归循环崩溃。

使用defs的代码:

trait T {
  def fields: List[Int] = Nil
}

trait A extends T {
  override def fields = 1 :: super.fields
}

trait B extends T {
  override def fields = 2 :: super.fields
}

val x = new B with A

println(x.fields)

lazy vals的代码:

trait T {
  def fields: List[Int] = Nil
}

trait A extends T {
  override lazy val fields = 1 :: super.fields
}

trait B extends T {
  override lazy val fields = 2 :: super.fields
}

val x = new B with A

println(x.fields)

为什么会这样?

1 个答案:

答案 0 :(得分:4)

我认为这与https://issues.scala-lang.org/browse/SI-3167

的情况相同
  

Scala编译器错误:可堆叠的特征和延迟的vals导致   StackoverflowException

trait Thing { def name: String }
trait Thing1 extends Thing { override lazy val name = "One" }
trait Thing2 extends Thing { abstract override lazy val name = super.name }
val t = new Thing with Thing1 with Thing2
t.name

结果为java.lang.StackOverflowError

你可以使它更相似。

trait Thing { def name: String = "" }
trait Thing1 extends Thing { override lazy val name = "One" }
trait Thing2 extends Thing { override lazy val name = super.name }
val t = new Thing with Thing1 with Thing2
t.name

这也会产生java.lang.StackOverflowError

无论如何,这个bug修复是他妈的推迟了。

Added the Fix Version 'Scala 2.11.3'
Removed the Fix Version 'Scala 2.11.2' 

Added the Fix Version 'Scala 2.11.2'
Removed the Fix Version 'Scala 2.11.1' 

Added the Fix Version 'Scala 2.11.1-RC1'
Removed the Fix Version '2.11.1-RC1' 

Added the Fix Version '2.11.1-RC1'
Removed the Fix Version 'Scala 2.11.0-RC1' 

Added the Fix Version 'Scala 2.11.0-RC1'
Removed the Fix Version 'Scala 2.11.0-M8' 

Added the Fix Version 'Scala 2.11.0-M8'
Removed the Fix Version 'Scala 2.11.0-M7' 

Added the Fix Version 'Scala 2.11.0-M6'
Removed the Fix Version 'Scala 2.11.0-M4' 

Added the Fix Version 'Scala 2.11.0-M4'
Removed the Fix Version 'Scala 2.11.0-M3' 

Added the Fix Version 'Scala 2.11.0-M3'
Removed the Fix Version 'Scala 2.11.0-M2' 

...

2010年报道了这个问题。

我建议不要使用在可堆叠特征中调用lazy val的{​​{1}}。