2011-12-15 14 views
5

Bieg:Scala Stream zamieszanie

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

będę oczekiwać:

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

I otrzymujemy:

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

mógłbyś mi to wyjaśnić?

+2

Dlaczego miałbyś oczekiwać, że 'x.head' zwróci listę? – sepp2k

+0

Co mnie martwi to dlaczego na ziemi chcesz umieścić 'println' w definicji leniwe val. –

+2

@Dan: Aby dowiedzieć się, kiedy i jak często będzie wykonywane wyrażenie (i jakie będą różne wartości, kiedy to nastąpi), wyobrażam sobie. – sepp2k

Odpowiedz

5

Powodem, dla którego uzyskujesz Int zamiast List jest to, że s jest strumieniem liczb całkowitych, więc zawiera liczby całkowite, a nie listy.

Powodem, dla którego otrzymujesz 3 jest to, że ogon (1,2,3,4,5, ...) (tj. s) to (2,3,4,5, ...), a jeśli zamapujesz +1 na to, otrzymasz (3,4,5,6,7, ...), a główka tego jest 3.

Powodem, dla którego drukowana jest tylko jedna liczba całkowita, jest wyrażenie oceniane tylko raz, aby uzyskać strumień dla ogona. Następnie oceniany jest tylko strumień zwracany przez s.tail.map(_+1) (który nie zawiera żadnych instrukcji drukowania).

+0

rozważ to: 'val s: Stream [Int] = 1 # :: 2 # :: {val x = s.tail.map (1+); x wykonaj 10 wydruków; x} 'wypisze' 3333 ... 'i upada, więc' x' wydaje się być strumieniem trójek, a nie 3,4,5, ... ale to nie ma sensu, ponieważ wtedy 's' powinno być' Strumień (1,2,3,3,3, ...) ". Jestem tak zagubiony, jakakolwiek rada, gdzie mogę przeczytać więcej o strumieniach? – 4e6

+0

@ 4e6: Zużywanie większej ilości elementów strumienia niż zostało wygenerowane w wyrażeniu generującym strumień, spowoduje nieskończoną rekurencję (która w końcu wysadzi stos). Powodem, dla którego dostajesz tak dużo 3s, nie jest to, że strumień zawiera tyle 3s (gdyby były rozdzielone przecinkami), ale instrukcja print jest wykonywana tyle razy (ponieważ logika powraca w kółko i dostaje się do instrukcja drukowania raz za razem ...). – sepp2k

+0

@ 4e6 Zastanów się, co napisałeś: aby obliczyć trzecią liczbę, musi wydrukować 10 pierwszych liczb. Ale jak może wydrukować trzecią liczbę, jeśli jeszcze jej nie obliczono? To ty dostałeś błąd. –