2016-07-02 21 views
1

Ich versuche, die ersten 10 Fibonacci-Zahlen wie folgt zu erhalten:generieren erste 10 Fibonacci-Zahlen unendlichen Strom mit

(take 10 (fn fibgen [a b] (cons a (fibgen b (+ a b))) 0 1)) 

Die Idee ist, dass fibgen eine faule Sequenz erzeugt (ein unendlicher Strom). Leider gibt dies den folgenden Fehler:

IllegalArgumentException Don't know how to create ISeq from:
user$eval10144$fibgen__10145 clojure.lang.RT.seqFrom (RT.java:528)

Wie kann das behoben werden?

+2

Sie nie die Funktion aufrufen, und wenn Sie es nennen es gewonnen bin nicht faul – noisesmith

+0

@noissmith ich sehe jetzt tatsächlich. :) –

Antwort

3

Ich denke, Sie haben gerade einen Tippfehler gemacht. Hier ist, was Ihre fibgen Funktion wie neu formatiert aussieht:

(fn fibgen [a b] 
    (cons a (fibgen b (+ a b))) 
    0 
    1) 

Diese Funktion realisiert die gesamte Fibonacci-Folge, beginnend mit a und b, dann kehrt 1. Was Sie zu tun war, bedeutete eine Funktion definieren, die die Sequenz zurückgibt, Anruf mit 0 und 1, und nehmen dann die ersten zehn Elemente aus dieser Sequenz:

(take 10 ((fn fibgen [a b] (cons a (fibgen b (+ a b)))) 0 1)) 

Wenn Sie dies ausführen, erhalten Sie eine ArithmeticException für integer-Überlauf kommen, da Zahlen in der Fibonacci-Folge schnell die r verlassen Ange einer 64-Bit-Ganzzahl. Sie können dies mit +' beheben:

(take 10 ((fn fibgen [a b] (cons a (fibgen b (+' a b)))) 0 1)) 

Da Clojure nicht faul ist, wird dies versuchen, die gesamte Fibonacci-Folge zu realisieren, die eine StackOverflowError verursachen. Auch wenn Clojure selbst nicht faul ist, aber Sie können erstellen lazy sequence, die im Grunde die gleiche Wirkung in diesem Fall haben:

(take 10 ((fn fibgen [a b] (lazy-seq (cons a (fibgen b (+' a b))))) 0 1)) 
;;=> (0 1 1 2 3 5 8 13 21 34) 
+0

Danke. Noch eine Frage, die ich dir beantworten kann: Wenn Clojure nicht faul ist, warum erstellt 'map' dann einen faulen Seq? Siehe [diese frühere Frage] (http://stackoverflow.com/questions/36715935/code-not-called-from-go-block-but-it-works-from-repl#36717600). –

+1

Clojure ist eine strikte Sprache, was bedeutet, dass Werte standardmäßig in einer realisierten Form gespeichert werden und nicht als Thunks gespeichert werden, die nur bei Bedarf realisiert werden. Dies bedeutet jedoch nicht, dass Sie keine Thunks verwenden können. Die Funktion ['map'] (https://github.com/clojure/clojure/blob/clojure-1.8.0/src/clj/clojure/core.clj#L2618-L2665) verwendet den [' lazy-seq' ] (https://github.com/clojure/clojure/blob/clojure-1.8.0/src/clj/clojure/core.clj#L664-L671) Makro, das einen Code in eine Null-Funktion einfügt und zurückgibt ein Objekt, das diese Funktion nur aufrufen und zwischenspeichern wird, wenn sie dazu aufgefordert wird. –