100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Lazy Sequences

Understand how Clojure's lazy sequences defer computation until it's needed, enabling infinite sequences, and learn the chunking and memory pitfalls that trip up beginners.

Functional ProgrammingIntermediate10 min readJul 10, 2026
Analogies

What Makes a Sequence Lazy?

A lazy sequence in Clojure is a sequence whose elements are computed on demand rather than up front; functions like map, filter, range, and iterate return lazy seqs backed by a chain of unrealized computations wrapped in LazySeq objects. Because nothing is computed until you ask for it, by calling first, seq, or forcing realization another way, you can define sequences that are conceptually infinite, like (range) or (iterate inc 0), without running out of memory.

🏏

Cricket analogy: A ball-by-ball radio commentary that only describes a delivery once it's actually bowled, never pre-narrating overs that haven't happened yet, mirrors laziness — computation happens on demand.

Building Infinite Sequences

iterate, repeat, and cycle all produce infinite lazy sequences: (iterate f x) yields x, (f x), (f (f x)), and so on forever; (repeat x) yields x infinitely; (cycle coll) loops coll forever. You must always combine these with a bounding function like take, take-while, or nth to pull a finite, realized piece out — calling something like (count (iterate inc 0)) will hang forever trying to realize an infinite sequence.

🏏

Cricket analogy: An automated bowling machine set to fire balls indefinitely at a fixed speed, from which a coach only records the first 6 deliveries for analysis, mirrors (take 6 (repeat ball)).

clojure
(take 5 (iterate #(* 2 %) 1)) ;=> (1 2 4 8 16)
(take 4 (cycle [:a :b :c])) ;=> (:a :b :c :a)
(take-while #(< % 100) (iterate inc 1))

Calling a realizing function like count, reverse, or into on an infinite lazy sequence without first bounding it with take or take-while will hang the process indefinitely — always bound infinite sequences before forcing realization.

Chunking and Realization Pitfalls

Many core lazy sequences (those built on vectors, like (map f (range 1000000))) are chunked in blocks of 32 for performance, meaning realizing one element can silently force up to 31 more; this matters when your function has side effects, since you may see them fire in unexpected batches of 32. Using dorun or doall explicitly forces realization for its side effects or memory-pinning behavior, and holding onto the head of a lazy sequence (for example, in a def) can cause the whole realized sequence to stay in memory, a classic Clojure memory leak.

🏏

Cricket analogy: A TV broadcaster who, when you ask to see just one replay, actually processes a whole batch of 32 camera angles behind the scenes before showing you the one you asked for, mirrors chunked lazy realization.

clojure
(def head (map #(do (println "computing" %) %) (range 100)))
(first head) ;; prints "computing 0" through "computing 31" due to chunking

If you need to force every side effect in a lazy sequence without keeping the results, use (dorun ...); if you also need the realized values retained, use (doall ...).

  • Lazy sequences compute elements on demand rather than eagerly, backed by LazySeq objects.
  • iterate, repeat, and cycle can produce conceptually infinite sequences.
  • Infinite sequences must always be bounded with take, take-while, or similar before being realized.
  • Many built-in lazy sequences are chunked in blocks of 32 for performance, which can affect side-effect timing.
  • dorun forces realization for side effects without retaining results; doall forces realization and retains results.
  • Holding a reference to the head of a large lazy sequence, e.g. via def, can prevent garbage collection and leak memory.
  • Laziness lets you express algorithms declaratively without worrying about how much of a sequence will actually be used.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#ClojureStudyNotes#LazySequences#Lazy#Sequences#Makes#Sequence#StudyNotes#SkillVeris#ExamPrep