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
twoThis 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.