Channel Directions in Elixir
In Elixir, we can specify the direction of data flow in function parameters using the send_only
and receive_only
modifiers. This specificity increases the type-safety of the program.
defmodule ChannelDirections do
# This `ping` function only accepts a channel for sending
# values. It would be a compile-time error to try to
# receive on this channel.
def ping(pings, msg) do
send(pings, msg)
end
# The `pong` function accepts one channel for receives
# (pings) and a second for sends (pongs).
def pong(pings, pongs) do
receive do
msg -> send(pongs, msg)
end
end
def main do
pings = spawn_link(fn -> receive_loop() end)
pongs = spawn_link(fn -> receive_loop() end)
ping(pings, "passed message")
pong(pings, pongs)
receive do
msg -> IO.puts(msg)
end
end
defp receive_loop do
receive do
msg -> send(self(), msg)
end
receive_loop()
end
end
ChannelDirections.main()
To run the program:
$ elixir channel_directions.exs
passed message
In this Elixir version, we use processes and message passing to simulate channels. The ping
and pong
functions send messages to processes, and we use receive
blocks to handle incoming messages.
The main
function creates two processes (pings
and pongs
) that act as our channels. We then call ping
and pong
with these processes, and finally, we wait to receive and print the final message.
Note that Elixir doesn’t have built-in channel direction specifications like Go does. However, the actor model and message passing in Elixir provide a similar level of concurrency control.