2009-07-16 9 views

Répondre

10

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.

+0

+1 pour le deuxième exemple! –

4

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))) 
Questions connexes