for and sequence comprehensions
Basicforclojure.core/forList comprehension; lazy. (for [x xs :when (p x)] (f x)).view on clojuredocs → is Clojure's list comprehension: a single expression that
generates a lazy seq by walking one or more bindings, optionally filtering
and binding intermediates along the way. The look is borrowed from
mathematical set-builder notation — {x * x | x ∈ xs, x odd} — and the
shape is the same: bindings on the left, an expression on the right.
Don't confuse forclojure.core/forList comprehension; lazy. (for [x xs :when (p x)] (f x)).view on clojuredocs → with doseqclojure.core/doseqLike for, but for side effects; returns nil.view on clojuredocs →. forclojure.core/forList comprehension; lazy. (for [x xs :when (p x)] (f x)).view on clojuredocs → builds a value (a lazy seq). doseqclojure.core/doseqLike for, but for side effects; returns nil.view on clojuredocs → runs side effects (returns nil). Same syntax, different intent.
Minimal example
A single binding behaves like mapclojure.core/mapApply f to each element, returning a lazy seq.view on clojuredocs →:
Two bindings nest — the rightmost varies fastest. This is the cartesian product of the two collections:
Six pairs, in row-major order: :red :s, :red :m, :red :l,
:blue :s, …
Modifiers: :when, :while, :let
Inside the binding vector you can interleave three modifier keywords:
:when expr— skip this iteration ifexpris falsy.:while expr— stop the innermost binding whenexprbecomes falsy.:let [k v …]— bind locals visible to the rest of the form.
:let is the cleanest way to compute something once per iteration without
repeating yourself:
:while exits early — useful when the source is infinite:
Without :while, that would never return. With :while, the seq ends as
soon as the condition flips.
Practical example: pythagorean triples
The classic comprehension. Two ordered bindings, a :when to filter for
the right relationship — one expression, no loops:
forclojure.core/forList comprehension; lazy. (for [x xs :when (p x)] (f x)).view on clojuredocs → is lazy
The body doesn't run until something pulls on the resulting seq. This means side effects inside forclojure.core/forList comprehension; lazy. (for [x xs :when (p x)] (f x)).view on clojuredocs → may never happen:
If you actually want the side effects, use doseqclojure.core/doseqLike for, but for side effects; returns nil.view on clojuredocs →:
Same shape, opposite purpose. The mnemonic: forclojure.core/forList comprehension; lazy. (for [x xs :when (p x)] (f x)).view on clojuredocs → is for values, doseqclojure.core/doseqLike for, but for side effects; returns nil.view on clojuredocs → is for effects.
Check yourself
? quiz
What does `(for [x [1 2 3] y [10 20]] [x y])` return?
Exercise
Write a single forclojure.core/forList comprehension; lazy. (for [x xs :when (p x)] (f x)).view on clojuredocs → expression that returns every (row, col) pair on an
8×8 chessboard whose squares are dark — by convention, a square is dark
when (even? (+ row col)). The result should be a seq of 32 pairs.