2016-05-22 10 views
2

Warum funktioniert dasfaul-Seq Stackoverflow

(def fibs (cons 0 (cons 1 (lazy-seq (map + fibs (rest fibs)))))) 
(take 10 fibs) 

während dieser andere

(def fibs (lazy-seq (cons 0 (cons 1 (map + fibs (rest fibs)))))) 
(take 10 fibs) 

eine Stackoverflow generieren?

+0

Was versuchen Sie mit 'Lazy-Seq' zu erreichen? Es scheint gut zu laufen, wenn Sie es einfach entfernen. – jmargolisvt

+0

@jmargolisvt Auf meinem repl (clojure 1.6) funktioniert der Code '(def fabs (cons 0 (Nachteile 1 (map + fabs (rest fibs))))) nicht. Lazy-seq ist notwendig, denke ich, weil es die Berechnung des Streams verzögert, sonst wird es nicht funktionieren, indem es die Fibs in Form von Fibs selbst definiert – Matteo

Antwort

4

erste Note Lassen Sie sich, dass es funktioniert auch mit einem cons außen:

(def fibs (cons 0 (lazy-seq (cons 1 (map + fibs (rest fibs)))))) 

sie schafft auch, dass lazy-seq ein Makro (offensichtlich, da sie nicht die Argumente nicht auswertet) und setzt das body (das Argument (s) zu lazy-seq) zu einer Funktion.

Wenn Sie jetzt ein Element aus dieser Sequenz "anfordern", wird die Funktion einmal aufgerufen und nachfolgende Aufrufe geben den zwischengespeicherten Wert zurück.

Offensichtlich, nur einmal, dass die Funktion etwas zurückgibt, haben Sie einen Wert verfügbar. Nun, was passiert in unserem schlechten Fall:

Stellen Sie sich clojure ist in der Mitte der Bewertung der Funktion zum allerersten Mal. Die erste Sache, die es benötigt, ist +, fibs und (rest fibs), um dies an Nachteile zu übergeben. Jetzt wird clojure sehen, dass fibs eine faule Sequenz ist und rufe sie auf! Dies liegt daran, dass Sie sich gerade in Ihrem ersten Aufruf befinden und nicht zurückgekehrt sind. Dies verursacht eine unendliche Rekursion.

Die Lösung ist einfach: Stellen Sie sicher, dass ein reales Element am Anfang der Liste vorhanden ist, so dass die beiden Ausdrücke fibs und (rest fibs) etwas zurückgeben können. Insbesondere die rest von (cons 1 whatever) wird whateverwithout realizing a single element (wichtig, da sonst wir das gleiche Problem wieder haben) zurückgeben.