🎓 A1Learner
🔍
0 of 54 lessons completed

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?