Search⌘ K
AI Features

Streams: Lazy Enumerables

Explore how Elixir uses streams as lazy enumerables to process collections efficiently without generating intermediate results. Understand the difference between Enum and Stream modules, how streams enable composable pipelines, and how to handle large or infinite data sequences. This lesson helps you write more memory-efficient and performant Elixir code by using streams instead of eager enumeration.

In Elixir, the Enum module is greedy. This means that when we pass it a collection, it potentially consumes all the contents of that collection. It also means the result will typically be another collection. Look at the following pipeline:

[ 1, 2, 3, 4, 5 ]
#=> [ 1, 2, 3, 4, 5 ]

|> Enum.map(&(&1*&1))
#=> [ 1, 4, 9, 16, 25 ]

|> Enum.with_index
#=> [ {1, 0}, {4, 1}, {9, 2}, {16, 3}, {25, 4} ]

|> Enum.map(fn {value, index} -> value - index end) 
#=> [1, 3, 7, 13, 21]

|> IO.inspect 
#=> [1, 3, 7, 13, 21]

The first map function takes the original list and creates a new list of its squares. Using with_index takes this list and returns a list of tuples. The next map then subtracts the index from the value, generating a list that gets passed to IO.inspect.

So, this pipeline generates four lists on its way to outputting the final result.

Let’s look at something different. Here’s some code that reads lines from a file and returns the longest line:

IO.puts File.read!("/usr/share/dict/word
...