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") endAfter 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") endSkipped 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") endExample
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") endKey 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?