Clojure `for`, `doseq` & List Comprehensions — Generate and Iterate with Clarity | Episode 19
0views
C
CelesteAI
Description
`for` is Clojure's list comprehension — give it one or more bindings and it hands back a lazy sequence of results. Add `:when` to filter, `:let` to name intermediate values, and you have a compact language for "generate me everything shaped like X."
`doseq` has the exact same shape, but it's eager and returns nil. You reach for it when you want the side effects — printing, writing, logging — not a collection.
In this episode we build chess-board coordinates with `for`, filter dark squares with `:when`, find Pythagorean triples with `:let`, and print a multiplication table with `doseq`.
Student code: https://github.com/GoCelesteAI/clojure-for-beginners/tree/main/episode19
Every keystroke is shown on screen with generous pauses so you can follow along at your own pace.
What You'll Learn:
- `for` as a list comprehension — bindings in, lazy seq out
- Multiple bindings — Cartesian product, rightmost varies fastest
- `:when` — inline filter over the bindings
- `:let` — name intermediate values mid-comprehension
- `doseq` — eager, nil-returning sibling for side effects
- The rule of thumb: `for` for values, `doseq` for effects
Timestamps:
0:00 - Intro
0:15 - Preview: generate & iterate with clarity
0:38 - Start the REPL
0:52 - `for` with a single binding
1:05 - Multiple bindings
1:30 - `:when` filters
1:43 - `doseq` in the REPL
1:59 - Exit REPL
2:12 - Write for_doseq.clj in Neovim
2:40 - `for` section
3:15 - Multiple bindings section
3:55 - Chess board coordinates
5:00 - `:when` filters section
5:40 - `:let` bindings & Pythagorean triples
6:50 - `doseq` section
7:45 - Multiplication table with `doseq`
8:40 - Run with clj -M
8:45 - Output walked through
9:55 - Review
10:10 - Recap
10:45 - What's next: Episode 20
Key Takeaways:
1. `for` returns a lazy sequence — it describes what to generate.
2. Multiple bindings nest — the rightmost binding varies fastest.
3. `:when` filters bindings inline, `:let` names intermediate values.
4. `doseq` shares `for`'s shape but runs eagerly and returns nil.
5. If you find yourself throwing a `for` result away, you want `doseq`.
Phase 3 — Functional Core — is now complete. Next up, Phase 4 kicks off with Episode 20: Namespaces and `require`.
Taught by CelesteAI. Like and subscribe for more Clojure tutorials!