Clojure recursion, loop/recur.


;;; Clojure recursion
(defn every-other [coll]
  (if (empty? coll)
      '()
      (conj (every-other (rest (rest coll))) (first coll))))

(every-other '(2 3 4))
(every-other [])
(every-other [2])
(every-other (take 10 (range)))

;; You can write this in tail-recursive fashion:
(defn every-other2 [coll result]
  (if (empty? coll)
      result
      (every-other2 (rest (rest coll)) (conj result (first coll)))))

(every-other2 '(2 3 4) '())
(every-other2 [] '())
(every-other2 [2] '())
(every-other2 (take 10 (range)) '())

;; However, Java doesn't optimize tail recursion
;; Clojure has a loop-recur form for tail recursion:
(defn every-other-loop [coll]
  (loop [c coll r '()]
    (if (empty? c)
        r
        (recur (rest (rest c)) (conj r (first c))))))

;; This is almost correct, except the order is reversed (why?)
(every-other-loop '(2 3 4))
(every-other-loop [])
(every-other-loop [2])
(every-other-loop (take 10 (range)))

;; Passing [] as initial value for r in loop/recur
;; changes the order of adding elements via conj
(defn every-other-loop2 [coll]
  (loop [c coll r []]
    (if (empty? c)
        r
        (recur (rest (rest c)) (conj r (first c))))))

;; This is almost correct, except the order os reversed (why?)
(every-other-loop2 '(2 3 4))
(every-other-loop2 [])
(every-other-loop2 [2])
(every-other-loop2 (take 10 (range)))

CSci 4651 course web site.

The views and opinions expressed in this page are strictly those of the page author. The contents of this page have not been reviewed or approved by the University of Minnesota.