For in Clojure

Clojure provides several ways to create loops. Let’s explore some basic types of loops.

(ns for-example.core
  (:gen-class))

(defn -main []
  ;; The most basic type, with a single condition.
  (loop [i 1]
    (when (<= i 3)
      (println i)
      (recur (inc i))))

  ;; A classic initial/condition/after loop using dotimes.
  (dotimes [j 3]
    (println j))

  ;; Another way of accomplishing the basic "do this N times" iteration
  ;; is using doseq with a range.
  (doseq [i (range 3)]
    (println "range" i))

  ;; Clojure doesn't have a direct equivalent to an infinite loop,
  ;; but we can create one using loop and recur.
  (loop []
    (println "loop")
    (if (< (rand) 0.5)
      (recur)))

  ;; You can also use continue-like behavior with recur.
  (doseq [n (range 6)]
    (when-not (even? n)
      (println n))))

To run the program:

$ lein run
1
2
3
0
1
2
range 0
range 1
range 2
loop
1
3
5

In this example:

  1. We use loop and recur to create a basic loop with a condition.
  2. dotimes is used for a classic “do this N times” iteration.
  3. doseq with range is another way to iterate a specific number of times.
  4. An infinite loop is created using loop and recur with a random condition to break out.
  5. We demonstrate continue-like behavior using when-not inside a doseq.

Clojure’s looping constructs are quite different from imperative languages, emphasizing functional programming concepts. The recur special form is used for tail-recursion optimization, which is how Clojure achieves efficient looping without mutable state.

We’ll see other forms of iteration later when we look at sequences, lazy sequences, and other data structures.