2012-11-16 26 views
6

Próbuję zrozumieć wykonanie następującego kodu:Zrozumienie wykonanie leniwe realizacji Fibonacciego w Clojure

(def fibs 
    (concat (lazy-seq [0 1]) (lazy-seq (map + fibs (rest fibs))))) 

To co by się spodziewać wykonanie wyglądać

[0 1 : (map + [0 1] [1]) => 1 
[0 1 1 : (map + [0 1 1] [1 1]) => 1 2 
[0 1 1 1 2 : (map + [0 1 1 2] [1 1 2]) => 1 2 3 
[0 1 1 1 2 1 2 3 : (map + [0 1 1 2 3] [1 1 2 3]) => 1 2 3 5 
[0 1 1 1 2 1 2 3 1 2 3 5 .... 

Co jest oczywiście niepoprawne, ponieważ wynik jest nieprawidłowy. Jedynym wykonanie mogłem wymyślić, że produkowane poprawny wynik to:

[0 1 : (map + [0 1] [1]) => 1 
[0 1 1 : (map + [1 1] [1]) => 2 
[0 1 1 2 : (map + [1 2] [2]) => 3 
[0 1 1 2 3 : (map + [2 3] [3]) => 5 
[0 1 1 2 3 5 .... 

Czy to jest poprawne „reprezentacja” stanu głowę i ogon w trakcie realizacji? Jeśli tak, dlaczego (rest fibs) zwraca jeden przedmiot? Czy to z powodu wywołania rekurencyjnego (reszta (reszta [reszta [1 1 2 3])))?

Odpowiedz

6

Fibs to (0 1 ...) (ze względu na (concat [0 1] ...) na początku). (rest fibs) to (1 ...). Następnie (map + fibs (rest fibs)) jest

((+ 0 1) ...) => (1 ...) 

Więc bujda jest (0 1 1 ...). Ponieważ mamy kolejny element, możemy obliczyć jeszcze jeden:

(1 (+ 1 1) ...) => (1 2 ...) 

i idzie na ...

(1 2 (+ 1 2) ...) 

Pomyśl o bujda jakby to był już tam, a państwo z (map + fibs (rest fibs) jako przejściem na liście kłamstw, które już istnieją (to dobrze, ponieważ kończy się obliczanie wszystkiego, czego potrzebujemy w drodze).

Może to również pomóc tylko zanotować dwie sekwencje:

(0 1 1 2 3 5 ...) 
+(1 1 2 3 5 ...) 
=(1 2 3 5 8 ...) 

(będę rysować strzałki tu wskazać, co już dostał i gdzie wynik idzie, ale nie mogę tego zrobić tutaj tak dobrze).