Elixir Send and Receive
Message passing is how one process sends a value to another process. The receiving process waits in a receive block and matches each message against patterns.
A process can message itself
send puts the atom :hello into this process's own mailbox. The receive block then takes it out and returns its branch value.
send(self(), :hello)
message =
receive do
:hello -> "hello received"
end
IO.puts(message)A spawned process replies with a doubled value
The spawned process waits for a {:ping, value} message and replies to the saved parent PID. The main code sends 21 and receives the doubled answer.
parent = self()
child =
spawn(fn ->
receive do
{:ping, value} -> send(parent, {:pong, value * 2})
end
end)
send(child, {:ping, 21})
answer =
receive do
{:pong, number} -> number
end
IO.puts(answer)Receive branches match message shapes
The message is a tuple holding an operation and two numbers. The matching branch binds both numbers and adds them.
send(self(), {:add, 3, 4})
result =
receive do
{:add, a, b} -> a + b
_other -> 0
end
IO.puts(result)Example
defmodule Echo do
def serve(parent) do
receive do
{:ping, value} -> send(parent, {:pong, value * 2})
end
end
end
parent = self()
child = spawn(Echo, :serve, [parent])
send(child, {:ping, 15})
answer =
receive do
{:pong, number} -> number
end
IO.puts("Answer: #{answer}")Key points
- Mailbox: each process has a mailbox, the place where arriving messages wait.
- Send: send(pid, message) puts the message into the mailbox of the process with that PID.
- Receive: a receive block waits until a message matches one of its patterns.
- Patterns: each receive branch matches a message shape and binds the values inside it.
- Return value: a receive block returns the value of the branch that matched.
- Order: messages from one sender to one process arrive in the order they were sent.
In this example, Echo.serve is spawned with the parent PID as its argument, so it knows where to reply. The main code sends {:ping, 15}, the echo process replies {:pong, 30}, and the receive block returns 30 for the printed line.
Note
send never waits, so the sender keeps running while the message is on its way.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does a receive block return?