🎓 A1Learner
🔍
0 of 46 lessons completed

Elixir Selective Receive

Selective receive is a receive block that picks a matching message first, even if it is not at the front of the queue. Messages that do not match stay in the queue.

A matching message jumps the queue

The second message matches, so it is read before the first.

send(self(), :ping)
send(self(), :pong)
receive do :pong -> IO.puts("pong") end
receive do :ping -> IO.puts("ping") end

After runs when nothing matches

No matching message arrives, so the after clause runs at once.

send(self(), :hello)
receive do
  :missing -> IO.puts("found")
after
  0 -> IO.puts("timeout")
end
receive do :hello -> IO.puts("hello") end

Skipped messages stay queued

One message is skipped, so it is still waiting after the other is read.

send(self(), :a)
send(self(), :b)
receive do :b -> IO.puts("b") end
{:message_queue_len, len} = Process.info(self(), :message_queue_len)
IO.puts(len)
receive do :a -> IO.puts("a") end

Example

send(self(), :red)
send(self(), :green)
send(self(), :blue)
receive do :green -> IO.puts("green") end
receive do :red -> IO.puts("red") end
receive do :blue -> IO.puts("blue") end

Key points

  • Matching: A receive clause reads the first message that matches its pattern.
  • Skipping: Messages that do not match are skipped for now and stay queued.
  • Order: A later message can be read before an earlier message that does not match.
  • Timeout: An after clause runs when no matching message arrives in time.
  • Staying: A skipped message can still be read by a later receive.

In this example, three messages wait in the queue. The receive blocks pick green first, then red, then blue, so the printed order differs from the arrival order.

Note

Selective receive does not delete skipped messages.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

You send :a then :b. A receive clause matches only :b. What does it read first?