The following are both meant to create a Stream of integers:
val s: Stream[Int] = 1 #:: s.map(_ + 1)
def makeStream = {
val s: Stream[Int] = 1 #:: s.map(_ + 1)
s
}
The first is fine; however the makeStream
method won't compile:
error: forward reference extends over definition of value s
val s: Stream[Int] = 1 #:: s.map(_ + 1)
^
It only compiles if we make s
a lazy val
. Why does it need to be a lazy val
in a method, but not outside?
Inside a class, a val
definition decompiles into an "getter" method that references a hidden class field. These "getter" methods can be self-referential (or rather, the class initializer can reference the "getter") because this is the semantics of Java methods. Note that your "outside" definition of val s
is actually wrapped in a hidden class by the REPL (this is how the REPL circumvents the restriction that a val
can't be declared at the top level).
Inside a method, the val
definition does not decompile into a "getter" method, but rather into the bytecode necessary to generate a value on the stack. A lazy val
, on the other hand, always requires a "getter" method which, as such, can be self-referential.