2016-07-02 2 views
1

Je suis en train d'obtenir les 10 premiers nombres de Fibonacci comme suit:10 premiers nombres de Fibonacci en utilisant flux infini

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

L'idée est que fibgen crée une séquence paresseuse (un flux infini). Malheureusement, cela donne l'erreur suivante:

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

Comment est-ce que ceci peut être fixé?

+2

vous n'appelez la fonction, et si vous ne l'appellent il a gagné ne soyez pas paresseux – noisesmith

+0

@noisesmith Je vois maintenant en effet. :) –

Répondre

3

Je pense que vous venez de faire une faute de frappe. Voici ce que votre fonction fibgen ressemble reformaté:

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

Cette fonction réalise toute la séquence de Fibonacci commençant par a et b, puis retourne 1. Qu'est-ce que vous vouliez dire à faire était de définir une fonction qui retourne la séquence, appel avec 0 et 1, puis prendre les dix premiers éléments de cette séquence:

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

Si vous exécutez, vous obtiendrez un ArithmeticException pour débordement d'entier, parce que les numéros dans la séquence de Fibonacci quittent rapidement le r ange d'un entier de 64 bits. Vous pouvez résoudre ce problème en utilisant +':

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

Depuis Clojure est pas paresseux, cela va essayer de réaliser la séquence de Fibonacci toute, ce qui entraînera une StackOverflowError. Même si Clojure est lui-même pas paresseux, cependant, vous pouvez créer un lazy sequence, qui aura essentiellement le même effet dans ce cas:

(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

Merci. Une autre question, j'espère que vous pouvez répondre: si Clojure n'est pas paresseux, pourquoi 'map' crée-t-il un seq paresseux? Voir [cette question antérieure] (http://stackoverflow.com/questions/36715935/code-not-called-from-go-block-but-it-works-from-repl#36717600). –

+1

Clojure est un langage strict, ce qui signifie que les valeurs sont, par défaut, stockées sous une forme réalisée au lieu d'être stockées sous forme de thunks qui sont réalisées uniquement en cas de besoin. Cependant, cela ne signifie pas que vous ne pouvez pas utiliser les thunk; la fonction ['map'] (https://github.com/clojure/clojure/blob/clojure-1.8.0/src/clj/clojure/core.clj#L2618-L2665) utilise le [' lazy-seq' ] (https://github.com/clojure/clojure/blob/clojure-1.8.0/src/clj/clojure/core.clj#L664-L671) macro, qui enveloppe un morceau de code dans une fonction nullaire et renvoie un objet qui appellera cette fonction (et mettra en cache son résultat) uniquement lorsqu'il lui sera demandé de le faire. –