Search code examples
listloopsclojurestack-overflowreverse

java.lang.StackOverflowError in clojure tail recursion


I encountered the StackOverflowError for the following code:

(defn recursive-reverse
  ([coll] (recursive-reverse [coll nil]))
  ([coll acc]
    (if (= coll '()) acc
        (recur (rest coll) (cons (first coll) acc)))))

though using loop would make it work:

(defn recursive-reverse [lst]
  (loop [coll lst acc nil]
    (if (= coll '()) acc
        (recur (rest coll) (cons (first coll) acc)))))

What goes wrong with the prior code without loop?


Solution

  • Your bug is here:

    ([coll] (recursive-reverse [coll nil]))
    

    You're calling recursive-reverse with one argument (a vector). This calls the same argument list of the function, so it does it recursively and creates a stack frame every time.

    Change it to:

    ([coll] (recursive-reverse coll nil))
    

    and you should be right.

    (Also, separate issue, but I would generally do checking for nil rather than '() and using next rather than rest. I don't think it has any real advantage in terms of performance or anything, but it seems cleaner to me.)