Подтвердить что ты не робот

Когда поток должен быть ленивым?

Ниже перечислены оба способа создания потока целых чисел:

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, но не снаружи?

4b9b3361

Ответ 1

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

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