~ / track A / clojure basics

for and sequence comprehensions

Basic

f‌o‌r 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 f‌o‌r with d‌o‌s‌e‌q. f‌o‌r builds a value (a lazy seq). d‌o‌s‌e‌q runs side effects (returns nil). Same syntax, different intent.

Minimal example

A single binding behaves like m‌a‌p:

loading sci
press ⌘/Ctrl-↵ or click ▶ run to evaluate

Two bindings nest — the rightmost varies fastest. This is the cartesian product of the two collections:

loading sci
press ⌘/Ctrl-↵ or click ▶ run to evaluate

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 if expr is falsy.
  • :while expr — stop the innermost binding when expr becomes falsy.
  • :let [k v …] — bind locals visible to the rest of the form.
loading sci
press ⌘/Ctrl-↵ or click ▶ run to evaluate

:let is the cleanest way to compute something once per iteration without repeating yourself:

loading sci
press ⌘/Ctrl-↵ or click ▶ run to evaluate

:while exits early — useful when the source is infinite:

loading sci
press ⌘/Ctrl-↵ or click ▶ run to evaluate

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:

loading sci
press ⌘/Ctrl-↵ or click ▶ run to evaluate

f‌o‌r is lazy

The body doesn't run until something pulls on the resulting seq. This means side effects inside f‌o‌r may never happen:

loading sci
press ⌘/Ctrl-↵ or click ▶ run to evaluate

If you actually want the side effects, use d‌o‌s‌e‌q:

loading sci
press ⌘/Ctrl-↵ or click ▶ run to evaluate

Same shape, opposite purpose. The mnemonic: f‌o‌r is for values, d‌o‌s‌e‌q is for effects.

Check yourself

? quiz

What does `(for [x [1 2 3] y [10 20]] [x y])` return?

Exercise

Write a single f‌o‌r 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.

loading sci
press ⌘/Ctrl-↵ or click ▶ run to evaluate
 status: new