以下两个都是为了创建一个整数流:
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
,而不是外部?
答案 0 :(得分:16)
在类中,val
定义反编译为引用隐藏类字段的“getter”方法。这些“getter”方法可以是自引用的(或者更确切地说,类初始化器可以引用“getter”),因为这是Java方法的语义。请注意,val s
的“外部”定义实际上是由REPL包装在一个隐藏的类中(这就是REPL规避了不能在顶层声明val
的限制的方式)。
在方法内部,val
定义不会反编译为“getter”方法,而是反编译为在堆栈上生成值所需的字节码。另一方面,lazy val
总是需要一种“吸气剂”方法,因此可以自我指导。