3.5. loops
Loops are an evaltime construct that allows dealing with repetetive code and lists of varying data, among other things.
The loop
and recur
ops are the basic building block of loops: loop
begins a recursive loop, and recur
is used to restart it:
(import* math logic string)
(loop (n 5)
(when (!= n 0)
(print (str "hello #" n))
(recur (- n 1))))
In this example, the (when …)
expression is the body of the loop, i.e. the
code that is repeated multiple times. In the head of the loop, loop definitions
can be introduced in a key-value syntax like with def
. Loop definitions are
valid only within the loop body and can be changed for each iteration of the
loop. Here a single symbol n
is defined to its starting value of 5
.
The loop body then starts being evaluated. Once it reaches the (recur …)
expression, the loop is restarted from the top, with the new value for n
given as the parameter. In this case, every new iteration of the loop has its
n
decremented by one, until n
is zero and therefore the (recur …)
expression is no longer reached.
Behind the scenes, loop
defines a new function for the dynamic symbol
*recur*
and immediately invokes it with the default values, and recur
simply calls this function. The example above could be equivalently rewritten
as follows:
(import* math logic string)
(defn loop-fn (n)
(when (!= n 0)
(print (str "hello #" n))
(loop-fn (- n 1))))
(loop-fn 5)