Why am I getting a stack overflow in the following Clojure function:
(defn length
[xs]
(if ,(not= xs nil)
(println (+ 1 (length (rest xs))))
(println 0)))
Why am I getting a stack overflow in the following Clojure function:
(defn length
[xs]
(if ,(not= xs nil)
(println (+ 1 (length (rest xs))))
(println 0)))
I think the idiomatic way of doing this is to call seq on your collection. seq on a collection returns nil if the collection is empty.
(defn length [xs]
(if (seq xs)
(inc (length (rest xs)))
0))
This isn't tail-recursive (you aren't using recur and can't here) so this will still overflow the stack on very large collections.
user> (println (length (range 1000000)))
;; stack overflow
One tail-recursive version would be
(defn length [xs]
(loop [xs xs
acc 0]
(if (seq xs)
(recur (rest xs) (inc acc))
acc)))
user> (println (length (range 1000000)))
1000000
This won't overflow the stack even for huge collections but it's still slow. Many Clojure collections implement the Counted interface and the built-in count function returns the length of those collections in constant time.