liveBook · Manning

Loop-recur

As explained in Clojure: The Essential Reference

recur is a Clojure special form that transfers control to the innermost enclosing loop or function form using replacement arguments.

`loop` and `recur` provide controlled repetition without a mutable loop counter. `loop` establishes local bindings; `recur` supplies their next values and restarts the innermost enclosing `loop` or function. When execution leaves the loop, its last expression supplies the result. section 3.4 section 3.4.1

Collect ten squares

```clojure (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] ``` Each `recur` supplies a replacement for both bindings. Once `i` reaches 10, the loop returns the accumulated vector. section 3.4

Choose the recursion target deliberately:

  • Inside a function, `recur` targets the innermost enclosing function if there is no nearer `loop`. A `loop` can instead initialize working values without adding function arguments. section 3.4.1
  • `recur` must be in tail position; the compiler rejects it elsewhere. Unlike an ordinary recursive call, it uses an optimization that does not consume stack space for each repetition. section 3.4.1

Keep working values local

```clojure (defn fib [n] (loop [a 1 b 0 cnt n] (if (zero? cnt) b (recur (+ a b) a (dec cnt))))) (map fib (range 10)) ;; (0 1 1 2 3 5 8 13 21 34) ``` The function accepts only `n`; the loop owns the additional values needed for iteration. For collection-wide tests, prefer an operation such as `every?` when it already expresses the job: its general implementation uses tail-recursive `recur`. section 3.4.1 section 8.1.5

How Clojure: The Essential Reference covers it

How deep it goes
Defines recursion targets and tail-position constraints, then works through examples and examines performance with benchmarks and JVM disassembly.
Examples
Demonstrates a square-number loop, Fibonacci calculation, square-root calculation, and performance measurements.
What it assumes
Assumes basic Clojure function and binding syntax while explaining how iteration passes values without mutation.
What you can do after
Build it from scratch: write a Clojure loop with replacement bindings and a tail-position recur.
How it connects
Connects loop-recur to tail recursion, function recursion, immutable local bindings, iterate, and collection predicates.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.