ELIXIR / CHAPTER 08
Lazy enumeration and bounded demand
AdvancedAvoid materializing work the consumer never needs.
By the end of this chapter
- Distinguish Enum from Stream timing
- Bound an unbounded producer before collection
- Keep side effects and repeated traversal explicit
The idea
Enum operations consume their input immediately and return results, while many Stream operations describe a lazy traversal. The lazy pipeline runs when a consumer enumerates it. This lets a program process large inputs incrementally or take a finite prefix from an unbounded source. Laziness does not mean the results are cached for future traversals.
Place limits before eager materialization. A pipeline that converts an infinite stream into a list before taking ten values never reaches the limiting step. Repeated enumeration can repeat callbacks and side effects, so keep transformations pure when the stream is intended to be reusable. Resource-backed streams also need a cleanup policy for normal completion and early termination.
result = Stream.iterate(1, &(&1 + 1))
|> Stream.filter(&(rem(&1, 2) == 0))
|> Stream.map(&(&1 * 3))
|> Enum.take(3)
IO.inspect(result)[6, 12, 18]
The consumer demands only three transformed even values, keeping the otherwise infinite producer bounded.
Try it yourself
Take the first five valid records from a lazy source without reading the rest unnecessarily.
Use your own editor for this exercise. Runnable challenges on CodeQuest are available for JavaScript, Python, and SQL.
CHECK YOUR UNDERSTANDING