2011-12-15 4 views
5

Running:Scala поток спутанность

lazy val s: Stream[Int] = 1 #:: 2 #:: {val x = s.tail.map(_+1); println("> " + x.head); x} 
s.take(5).toList 

Я бы ожидать:

> List(2, 3) 
> List(2, 3, 4) 
List(1, 2, 3, 4, 5) 

И я получаю:

> 3 
List(1, 2, 3, 4, 5) 

Не могли бы вы мне объяснить?

+2

Почему вы ожидаете, что 'x.head' вернет список? – sepp2k

+0

Что меня смущает, почему вы хотите поставить 'println' в определение ленивого val. –

+2

@Dan: Чтобы узнать, когда и как часто будет выполняться выражение (и какими будут различные значения, когда это произойдет), я полагаю. – sepp2k

ответ

5

Причина, по которой вы получаете Int вместо List, состоит в том, что s представляет собой поток целых чисел, поэтому он содержит целые числа, а не списки.

Причина, по которой вы получаете 3, состоит в том, что хвост (1,2,3,4,5, ...) (то есть s) равен (2,3,4,5, ...), и если вы нанесете +1 над этим, вы получите (3,4,5,6,7, ...), а голова - 3.

Причина, по которой печатается только одно целое, заключается в том, что выражение оценивается только один раз, чтобы получить поток для хвоста. После этого оценивается только поток, возвращаемый s.tail.map(_+1) (который не содержит никаких заявлений печати).

+0

рассмотрим это: 'val s: Stream [Int] = 1 # :: 2 # :: {val x = s.tail.map (1+); x возьмите 10 распечаток; x} 'будет печатать' 3333 ... 'и падает, поэтому' x' кажется потоком трех, а не 3,4,5, ... но это не имеет смысла, потому что тогда 's' должен быть' поток (1,2,3,3,3, ...) '. Я так смущен, какие-то советы, где я могу больше узнать о потоках? – 4e6

+0

@ 4e6: использование большего количества элементов потока, которые были созданы еще внутри выражения, генерирующего поток, вызовет бесконечную рекурсию (которая в конечном итоге взорвет стек). Причина, по которой вы получаете так много 3-х, заключается не в том, что поток содержит много 3-х (если бы они были разделены запятыми), но что оператор печати выполняется столько раз (потому что логика повторяется в кругах и добирается до заявление печати снова и снова и снова ...). – sepp2k

+0

@ 4e6 Подумайте, что вы написали: чтобы вычислить третье число, ему нужно напечатать 10 первых чисел. Но как он может напечатать третье число, если он еще не вычислил его? Это вы получаете ошибку. –