{:check ["true"]}

Index

Loop/recur

box

Section 2.6 - 2.7

Loop Recur

Loop/recur

The general form is:

(loop [<symbol> <initial-value>
       <symbol> <initial-value>
       ...]
    exprs*)

This evaluates to the last evaluated expression when the loop terminates.

The loop can contain:

(recur <value> <value> ...)

This starts the next iteration with new values for the <symbol> in the loop-binding.

Loop/recur is the most flexible form of iteration.

In [5]:
;
; Print messages
;
(loop [n 0]
    (when (< n 10)
        (do (println "Hello" n)
            (recur (inc n)))))
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
Hello 6
Hello 7
Hello 8
Hello 9
Out[5]:
nil
In [6]:
;
; Construct a sequence backwards
;
(loop [result []
       x 10]
    (if (zero? x)
        result
        (recur (conj result x) (dec x))))
Out[6]:
[10 9 8 7 6 5 4 3 2 1]
In [10]:
;
; x^2 + 4*y = x * y
;

(defn solution? [x y] (= (+ (* x x) (* 4 y)) (* x y)))

(loop [x 0
       y 0
       result []]
    (let [result' (if (solution? x y)
                      (conj result [x, y])
                      result)]
        (cond
            (< y 100) (recur x (inc y) result')
            (< x 100) (recur (inc x) 0 result')
            :else result)))
Out[10]:
[[0 0] [5 25] [6 18] [8 16] [12 18] [20 25]]
In [11]:
;
; The equivalent form in (for...)
;
(for [x (range 100)
      y (range 100)
      :when (solution? x y)]
    [x y])
Out[11]:
([0 0] [5 25] [6 18] [8 16] [12 18] [20 25])
  • Loop can be used to solve any iteration needs.
  • But it should be considered as the last resort. Other iteration forms are more readable, and easier to use.