liveBook · Manning

Dotimes

As explained in Clojure: The Essential Reference

dotimes is a Clojure macro that evaluates a body a specified number of times while binding an incrementing integer and returns nil.

dotimes repeats a body a specified number of times for side effects. Its binding vector supplies a local integer and a repetition count; the body may contain any number of expressions, and the macro always returns nil. section 3.4.5

The contract is:

  • Use exactly two binding-vector elements: [local n]. section 3.4.5
  • Evaluate the body with local starting at zero and incrementing by one. section 3.4.5
  • Skip the body when n is zero or negative. section 3.4.5
  • Return nil rather than collected results, making side effects the primary use. section 3.4.5

Printing indexed iterations

(dotimes [i 3] (println i)) ;; 0 ;; 1 ;; 2 ;; nil The index is also useful for repeated array access or transient-vector updates. For example, a transient result can be filled in place with (assoc! res i value), then converted with persistent!. section 3.4.5

Measuring repeated work

(time (dotimes [_ 1000000] (apply max (range 100)))) ;; "Elapsed time: ... msecs" ;; nil The ignored binding communicates that the iteration number is unnecessary. dotimes provides a quick timing loop, while more rigorous benchmarking can use Criterium. section 3.4.5

(macroexpand '(dotimes [i 3] (println i)))

;; (let* [n (long 3)]
;;   (loop [i 0]
;;     (when (< i n)
;;       (println i)
;;       (recur (unchecked-inc i)))))

The macro expands into a let*, loop, when, and recur, revealing a counted loop with an unchecked increment. section 3.4.5

Choose dotimes when computation exists for its effects and no results need collecting. Use sequence-oriented alternatives such as repeatedly when generated values are the result, or doseq when iterating over an existing collection. section 9.2.1 section 3.4.5

How Clojure: The Essential Reference covers it

How deep it goes
Defines the binding contract, edge cases, return value, examples, and macro expansion into a counted loop.
Examples
Uses indexed printing, timing with time, transient-vector construction, and comparison with repeatedly.
What it assumes
Assumes basic Clojure forms and local bindings while defining its two-element binding contract explicitly.
What you can do after
Apply it via Clojure's dotimes macro to perform a fixed number of indexed side effects.
How it connects
Connects side-effecting iteration with doseq, doall, dorun, run!, transient vectors, and repeatedly.

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.