Pourquoi ai-je un débordement de pile dans la fonction Clojure suivante:provoque un débordement de pile dans la fonction Clojure.
(defn length
[xs]
(if ,(not= xs nil)
(println (+ 1 (length (rest xs))))
(println 0)))
Pourquoi ai-je un débordement de pile dans la fonction Clojure suivante:provoque un débordement de pile dans la fonction Clojure.
(defn length
[xs]
(if ,(not= xs nil)
(println (+ 1 (length (rest xs))))
(println 0)))
Je pense que la façon idiomatiques de le faire est d'appeler seq
sur votre collection. seq
sur une collection renvoie nil
si la collection est vide.
(defn length [xs]
(if (seq xs)
(inc (length (rest xs)))
0))
Ce n'est pas récursive (vous n'utilisez pas recur
et ne peut pas ici) donc ce sera toujours déborder la pile sur de très grandes collections.
user> (println (length (range 1000000)))
;; stack overflow
Une récursive version serait
(defn length [xs]
(loop [xs xs
acc 0]
(if (seq xs)
(recur (rest xs) (inc acc))
acc)))
user> (println (length (range 1000000)))
1000000
Ce ne débordera pas la pile même pour les grandes collections, mais il est encore lent. De nombreuses collections Clojure implémentent l'interface Counted
et la fonction count
intégrée renvoie la longueur de ces collections à un instant constant.
+1 pour le deuxième exemple! –
Après le passage à tous seqs paresseux, le repos ne reviendra jamais nul, juste une liste vide - essayez ceci:
(defn length
[xs]
(if (not (empty? xs))
(println (+ 1 (length (rest xs))))
(println 0)))
OU ce
(defn length
[xs]
(if ,(not= xs nil)
(println (+ 1 (length (next xs))))
(println 0)))
Vous ne parlez pas de débordement de pile sur StackOverflow. lol –
Désolé, n'a pas pu résister. –
– MattC