I’m trying to recursively reverse a list, but am getting Can only recur from tail position upon run. What does this mean precisely and how can my code be improved so it works?
(defn recursive-reverse [coll]
(loop [coll coll]
(if (< (count coll) 2) '(coll)
(conj (first coll) (recur (rest coll)))
)))
EDIT
Output for Oscar’s solution. It works for lists but not vectors?
user=> (= (recursive-reverse [1 2 3 4 5]) (recursive-reverse '(1 2 3 4 5)))
false
user=> (= '(1 2 3 4 5) [1 2 3 4 5])
true
user=> (recursive-reverse [1 2 3 4 5])
[1 2 3 4 5]
user=> (recursive-reverse '(1 2 3 4 5))
(5 4 3 2 1)
The error
Can only recur from tail positionmeans that you’re not callingrecuras the last expression in the recursive part of the function – in fact, in your codeconjis the last expression.Some improvements to make your code work:
conjreceives a collection for its first parameter, not an elementconsinstead ofconj(which adds new elements at different places depending on the concrete type of the collection, according to the documentation). In this way the returned collection will be reversed if the input collection is either a list or a vector (although the type of the returned collection will always beclojure.lang.Cons, no matter the type of the input collection)'(coll)is a list with a single element (the symbolcoll) and not the actual collectionrecurat the tail position of the function; in this way each recursive invocation takes a constant amount of space and the stack won’t grow unboundedI believe this is what you were aiming for: