Browse Clojure Foundations for Java Developers

Lazy Sequences and Infinite Data Structures

Laziness changes when work happens; it enables streaming pipelines and infinite sequences.

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

Revised on Friday, April 24, 2026