Like most functional programming languages, Clojure emphasizes the use of recursion for iterated computation.

Example, merging two sorted lists:

(defn my-merge [left right]
  (cond
    (empty? left) right
    (empty? right) left
    (< (first left) (first right)) (cons (first left) (my-merge (rest left) right))
    :else (cons (first right) (my-merge left (rest right)))))

Example run:

user=> (def list1 '(1 5 9 33 50 97))
#'user/list1
user=> (def list2 '(3 6 28 44 67 68 99))
#'user/list2
user=> (my-merge list1 list2)
(1 3 5 6 9 28 33 44 50 67 68 97 99)

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-work [left right accum]
  (cond
    (and (empty? left) (empty? right)) (reverse accum)
    (empty? left) (recur left (rest right) (cons (first right) accum))
    (empty? right) (recur right (rest left) (cons (first left) accum))
    (< (first left) (first right)) (recur (rest left) right (cons (first left) accum))
    :else (recur left (rest right) (cons (first right) accum))))

(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.

(defn my-merge [left right]
  (loop [ll left
         rr right
         accum '()]
    (cond
      (and (empty? ll) (empty? rr)) (reverse accum)
      (empty? ll) (recur ll (rest rr) (cons (first rr) accum))
      (empty? rr) (recur rr (rest ll) (cons (first ll) accum))
      (< (first ll) (first rr)) (recur (rest ll) rr (cons (first ll) accum))
      :else (recur ll (rest rr) (cons (first rr) accum)))))