Stream in Elixir
| Streams are lazy | |
| Infinite streams | |
| Streams run on Enum | |
| Stream a file |
Streams are lazy
A stream describes work without doing it, holding a recipe instead of a result. Nothing runs until an Enum function pulls values through, which makes streams cheap to build and pass around.
s = Stream.map([1, 2, 3], &(&1 * 10))
is_struct(s, Stream)
The first line only stores the plan, and the check confirms a Stream struct with zero mapping applied. Laziness pays off when the source is large or endless, because no work happens before it is needed.
Infinite streams
Some streams never end, generating values on demand forever. Build them with iterate or cycle, then take only the prefix you need so the program stays finite.
Stream.iterate(1, &(&1 + 1))
|> Enum.take(4)
Iterate counts up from 1 without limit, and take collects the opening values 1, 2, 3, 4. Never feed an endless stream into a function that wants the whole collection, such as a full sort.
Streams run on Enum
Enum functions act as the engine that drives a stream to completion. Each pulled value flows through the lazy stages first, so filtering happens before collection with no middle list.
1..100
|> Stream.filter(&(rem(&1, 2) == 0))
|> Enum.take(3)
Only even numbers survive the filter, and take stops the flow after 2, 4, 6. The range end at 100 never matters, because the pipeline halts long before reaching it.
Stream a file
Files fit the streaming model well, since lines arrive one by one instead of loading the whole text at once. File.stream opens such a lazy line source for any path.
"notes.txt"
|> File.stream!()
|> Stream.map(&String.trim/1)
|> Enum.take(2)
Each line streams from disk, gets trimmed, and only two lines get collected for study. Huge logs and exports stay friendly with this pattern, using memory for one line at a time.
Next: Comprehensions in Elixir
Article author: Arthur Isaev