Когда поток должен быть ленивым? - PullRequest
12 голосов
/ 06 августа 2011

Следующие оба предназначены для создания потока целых чисел:

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 a lazy val.Почему он должен быть lazy val в методе, а не снаружи?

1 Ответ

16 голосов
/ 06 августа 2011

Внутри класса определение val декомпилируется в метод "getter", который ссылается на скрытое поле класса.Эти методы «получения» могут быть самоссылочными (или, скорее, инициализатор класса может ссылаться на «получение»), потому что это семантика методов Java.Обратите внимание, что ваше "внешнее" определение val s фактически обернуто в скрытый класс с помощью REPL (именно так REPL обходит ограничение, запрещающее объявлять val на верхнем уровне).

Внутри метода определение val не декомпилируется в метод "getter", а скорее в байт-код, необходимый для генерации значения в стеке.A lazy val, с другой стороны, всегда требует метода "getter", который, как таковой, может быть самоссылочным.

...