erlangreceivermessage-handlers

How to understand Erlang's receive statement?


I am new to Erlang, so please go easy on me.

I am confused as to how a receive statement is executed in erlang, for instance:

loop() ->
   receive
       MessageA -> handlerA();
       MessageB -> handlerB()
   end

If a MessageA is received, and handlerA executed, after a while, MessageB is received in the processes' inbox, does handlerB gets executed?

I guess not, since I see a lot of code that recurse to execute the receive statement again:

loop() ->
   receive
       MessageA -> 
          handlerA(),
          loop();
       MessageB -> 
          handlerB(),
          loop()
   end

But here is a problem, if messageA's handler includes another receive statement like this:

loop() ->
   receive
       MessageA -> 
          loop2(),
       MessageB -> 
          handlerB(),
          loop()
   end

 loop2() ->
   receive
      MessageC ->
          handlerC()
          loop2()
      MessageD ->
          handlerD()
          loop2()
   end

In this case, does it mean if I enter MessageA's hander, I can never handle MessageB?

And how can I resolve this? By putting MessageB's handler into loop2? This doesn't look very graceful, especially when there are multiple levels of receive statements.

Is there a better way to do this?


Solution

  • The following code means "execute receiving a single message", so if you want to receive more than one, you need to loop. The typical way of doing that in Erlang is to tail-call yourself.

    loop() ->
       receive
           MessageA -> handlerA();
           MessageB -> handlerB()
       end
    

    In your last example, it looks like you have some sort of state machine, where A changes to another state, whereas B stays in the same state. It is not necessarily a problem that you can no longer receive A messages when you're in the state where you expect C and D messages, but that would depend on the problem domain.