Ответ 1
Это не всегда рекурсивное определение. Это действительно работает и производит 1:
val a : Int = a + 1
println(a)
variable a
создается при вводе val a: Int
, поэтому вы можете использовать его в определении. Int
по умолчанию инициализируется 0. Класс будет нулевым.
Как заметил @Chris, Stream принимает => Stream[A]
, так что некоторые другие правила применяются, но я хотел объяснить общий случай. Идея остается прежней, но переменная передается по-имени, поэтому это приводит к рекурсивному вычислению. Учитывая, что он передается по имени, он выполняется лениво. Поток вычисляет каждый элемент один за другим, поэтому он вызывает ones
каждый раз, когда ему нужен следующий элемент, в результате чего тот же самый элемент создается еще раз. Это работает:
val ones: Stream[Int] = Stream.cons(1, ones)
println((ones take 10).toList) // List(1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
Хотя вы можете сделать бесконечный поток проще: Stream.continually(1)
Обновить Как @SethTisue указал в комментариях Stream.continually
и Stream.cons
два совершенно разных подхода с очень разными результатами, потому что cons
принимает a
, когда continually
принимает =>A
, что означает, что continually
перекомпонирует каждый раз элемент и сохраняет его в памяти, когда cons
может избежать его n раз, если вы не преобразуете его в другую структуру, например List
. Вы должны использовать continually
, только если вам нужно генерировать разные значения. См. Комментарий @SethTisue для деталей и примеров.
Но обратите внимание, что вам необходимо указать тип, то же, что и с рекурсивными функциями.
И вы можете сделать первый пример рекурсивным:
lazy val b: Int = b + 1
println(b)
Это будет stackoverflow.