Like most functional programming languages, Clojure emphasizes the use of recursion for iterated computation.
Example, merging two sorted lists:
Example run:
Issue: each function call in Clojure creates a new stack frame. So, a deep recursion could exhaust the stack (leading to a StackOverflowError
).
Solution: use the recur
form for recursive calls in tail position. A call is in tail position if the result of the call is returned as the result of the overall function. Note that my-merge
does not have its recursive calls in tail position, because a call to cons
is required after each recursive call to my-merge
returns. By adding a helper function with an accumulator parameter, we rewrite the function using recur
:
(defn my-merge [left right] (my-merge-work left right '()))
Note: because the accum
parameter holds the partial result of the computation, the cases where one of the lists (left
or right
) has become empty are slightly more complicated.
Question: Why is it necessary to reverse the accumulator in the case when both the left and right lists are empty?
Clojure defines the loop
form as a compact alternative to creating an explicit helper function.