Lazy Sequences in Clojure
Understand when Clojure sequence work is deferred, how lazy pipelines compose, and why infinite sequences are safe only when consumption is bounded.
Many Clojure functions return lazy sequences: they describe a computation, but do not perform all the work immediately. Work happens as you consume the sequence.
This is powerful:
- You can build streaming pipelines (transform as you go).
- You can represent infinite sequences safely when you take only what you need.
1(take 5 (range)) ;; => (0 1 2 3 4)
The gotchas to learn early
- If you keep a reference to the head of a lazy sequence, you can accidentally retain memory.
- Side effects inside lazy pipelines can be surprising because evaluation time is deferred.
Java mental model: laziness is closer to an iterator/stream that executes on demand, but it composes like plain functions.
In this section
-
How Lazy Sequences Work in Clojure
Learn how Clojure lazy sequences defer work, compose transformations, and differ from Java iterators and streams in evaluation timing.
-
Creating Lazy Sequences in Clojure
Create lazy sequences with lazy-seq, repeat, range, iterate, and sequence transformations while keeping realization and memory retention visible.
-
Infinite Sequences in Clojure
Work with unbounded Clojure sequences safely by pairing lazy producers with bounded consumers such as take, take-while, and finite reductions.
Revised on Saturday, May 23, 2026