下面两个语句都是用来创建一个整数流:
val s: Stream[Int] = 1 #:: s.map(_ + 1)
def makeStream = {
val s: Stream[Int] = 1 #:: s.map(_ + 1)
s
}
第一个很好;然而,makeStream
方法不会编译:
error: forward reference extends over definition of value s
val s: Stream[Int] = 1 #:: s.map(_ + 1)
^
只有当我们把s
变成lazy val
时才会编译。为什么在方法中需要lazy val
,而在方法外部不需要?
在类内部,val
定义反编译为引用隐藏类字段的"getter"方法。这些"getter"方法可以是自引用的(或者更确切地说,类初始化器可以引用"getter"),因为这是Java方法的语义。请注意,您的val s
的"外部"定义实际上是由REPL封装在一个隐藏类中(这就是REPL如何绕过val
不能在顶层声明的限制)。
在方法内部,val
定义不会反编译成"getter"方法,而是编译成在堆栈上生成值所需的字节码。另一方面,lazy val
总是需要一个"getter"方法,因此,它可以是自引用的。