Loop¶
loop and recur are the general way to repeat a body, and dotimes, while
and doseq cover the cases you meet most. Branching covers the
tests a loop body uses.
dotimes¶
dotimes runs a body a fixed number of times, counting from 0.0:
user=> (dotimes [i 3] (println "tick" i))
tick 0.0
tick 1.0
tick 2.0
nil
loop and recur¶
loop names values and recur starts the next round with new ones. The call
stack does not grow, so a loop can run for a whole match:
(loop [i 0]
(when (< i 3)
(println "tick" i)
(time/sleep 1)
(recur (inc i))))
recur must be the last thing its loop or function does, because there is
nothing left to return afterwards. Anything after it is a syntax error before
the code runs:
user=> (loop [i 0] (when (< i 3) (recur (inc i)) (println "after")))
Syntax error: Can only recur from tail position
recur also works directly in a function body, which is how a function loops:
user=> (defn count-down [n] (if (pos? n) (recur (dec n)) :done))
#'user/count-down
user=> (count-down 3)
:done
while¶
while is the shorter form when the test is the only state. It re-evaluates the
test each round, so a sensor reading is fresh:
user=> (let [i (atom 0)] (while (< @i 3) (swap! i inc)) @i)
3.0
On the robot you would read a sensor instead:
(while (> (distance) 10)
(drive 0.3))
doseq¶
doseq runs a body once for each item of a collection, and takes more than one
binding to nest:
user=> (doseq [m [1 2]] (println m))
1.0
2.0
nil
doseq takes no :when, :while or :let modifiers. Use when inside the
body, or filter the collection first.