Why are unmatched messages kept in the queue?

As specified in various websites, unmatched messages are kept in the queue. Why is it kept in the queue? When are they deleted from the queue?

**** Exact wordings from https://www.erlang.org/doc/getting_started/conc_prog.html: If there are no more patterns to test, the first message is kept in the queue

**** Exact wordings from the website https://uniwebsidad.com/libros/concurrent-erlang/chapter-1/concurrency:
The primitive receive takes the first message which matches one of the message patterns from a queue of messages waiting for the attention of the receiving process. If none of the receive patterns matches then the process is suspended until the next message is received – unmatched messages are saved for later processing.

3 Likes

They are not matched in the current receive, but there can be multiple different receives in each process.
Consider the following example:

1> MyFun = 
fun () ->
     receive {x, Msg} -> io:format("X matched") end, 
     receive {y, Msg} -> io:format("Y matched") end
end.
#Fun<erl_eval.43.3316493>
2> P = spawn(MyFun).
<0.88.0>
3> P ! {y, ok}.
{y,ok}
4> P ! {x, ok}.
X matched{x,ok}
Y matched

Even though the first message did not match at the first receive, it matched in the second one.

2 Likes

I would say that with the messaging model chosen by Erlang, i.e. a process having a single mailbox for incoming messages from all origins, selective receive is a necessity.

Without selective receive you wouldn’t be able to do communication in nested function calls without destroying the structure of the program, or inventing conventions like having a message queue somewhere in the process’ global state or passing that queue around all over the place (similar to how state is modelled in continuation-passing style denotational semantics).

(For a very simple and common example, consider a gen_server that while processing some particular message calls into some code which performs some other communication. That could be to an external system, or some local service that happens to be a separate process. Communication while handling other communication is as normal as recursive function calls are.)

There are alternatives that can do without selective receive, like channels and the ability to communicate over any number of channels, but they bring other complexities into the system.

So all in all I think Erlang got it right.

5 Likes

If you don’t want to save it to the queue, you can consume it

2 Likes

Thanks for the detailed response. I now understood the Selective receive. Erlang message processing is a lot different than Akka.

I am not aware of continuation-passing based concurrency. Also, I am few days into Erlang. I will read your response later to understand all the aspects explained by you.

1 Like

I now understand that we can delete unmatched messages from the mailbox using “Unexpected” as explained in More On Multiprocessing | Learn You Some Erlang for Great Good!

1 Like