Range Over Channels in Elixir
In a previous example, we saw how for
and comprehensions provide iteration over basic data structures. We can also use similar syntax to iterate over values received from a channel.
defmodule RangeOverChannels do
def main do
# We'll iterate over 2 values in the `queue` channel.
queue = Channel.new(2)
Channel.send(queue, "one")
Channel.send(queue, "two")
Channel.close(queue)
# This `receive` loop iterates over each element as it's
# received from `queue`. Because we closed the
# channel above, the iteration terminates after
# receiving the 2 elements.
for elem <- Channel.stream(queue) do
IO.puts(elem)
end
end
end
RangeOverChannels.main()
When you run this program, you’ll see:
$ elixir range_over_channels.exs
one
two
This example also showed that it’s possible to close a non-empty channel but still have the remaining values be received.
In Elixir, we don’t have built-in channels like in some other languages. Instead, we’re using a hypothetical Channel
module to simulate similar behavior. The for
comprehension with Channel.stream(queue)
is used to iterate over the channel’s values.
The concept of ranging over channels is similar to using Stream.resource/3
in Elixir for creating a stream from a stateful resource. In practice, you might use Elixir’s built-in concurrency primitives like processes and message passing to achieve similar functionality.