A loop repeats work while control values change. In Clojure, `loop` binds initial local values and `recur` supplies their values for the next pass. Unlike a Java `for` loop, this does not require a mutable counter or an outer collection to hold the result. section 3.4 section 3.4.1
(loop [i 0 s []]
(if (< i 10)
(recur (inc i) (conj s (* i i)))
s))
;; [0 1 4 9 16 25 36 49 64 81]
The counter starts at zero and the result starts as an empty vector. Each `recur` passes an incremented counter and a vector with one more square; when the test fails, the loop returns the vector. section 3.4
Choose the iteration form to match the work:
- Use `loop`/`recur` when successive local values determine the next step or when a computed result must be returned. `recur` targets the innermost enclosing `loop` or function, must be in tail position, and avoids consuming stack space on each pass. section 3.4.1
- Use `while` when a changing test depends on a side effect, particularly at a Java I/O boundary. It tests before each pass, so its body may not run; the loop terminates with `nil`. section 3.4.4
- For ordinary sequence work, prefer `range` with operations such as `map`, `filter`, or `for`. Use `dorun` when the purpose is to execute effects rather than retain the generated values. section 3.4.4
(defn fib [n]
(loop [a 1 b 0 cnt n] ; #1
(if (zero? cnt)
b
(recur (+ a b) a (dec cnt)))))
(map fib (range 10))
;; (0 1 1 2 3 5 8 13 21 34)
This Fibonacci function keeps its changing values inside `loop`, leaving the function argument alone. The zero-count branch returns the answer; the other branch supplies all three bindings to `recur`. section 3.4.1
A side-effecting `while` is not a substitute for a value-producing `loop`: repeatedly reading a Java input stream until its end is a fitting use, while accumulating values in a mutable atom is discouraged. For performance-sensitive iteration, `loop` can also propagate type information that helps avoid unnecessary boxing. section 3.4 section 3.4.1 section 3.4.4


























