[erlang-questions] erlang-questions Digest, Vol 12, Issue 98

Richard A. O'Keefe <>
Wed Jun 4 00:57:52 CEST 2008

I describe how selective multipattern receive could be done using
abstract patterns.

On 31 May 2008, at 2:42 am, John Haugeland wrote:

> So what's the advantage of that over something like this?
> isa_quit(State) ->
>     case State of
>         {?MODULE,{signal,{window1,_}}} -> true;
>         {?MODULE,{signal,{quit1,_}  }} -> true;
>         _                              -> false
>     end.

There was a clear distinction between states and messages.
The abstract patterns were there to match messages, not
> loop(State) ->
>     receive RcvState -> if
>         isa_quit(RcvState)       -> quit();
>         isa_connect(RcvState)    -> loop(conn(State));
>         isa_disconnect(RcvState) -> loop(disc(State));
>         isa_show_about(RcvState) -> loop(show_about(State));
>         isa_hide_about(RcvState) -> loop(hide_about(State));
>         isa_data(RcvState)       -> loop(update(State, RcvState));
>         X             -> io:fwrite("got ~p~n", [X]), loop(State)
>     end end.

Ah.  You confused me very effectively by using the "State" name in
the is_a_* functions, when you really meant "Message".  (Why would
you call something that isn't any kind of state "RcvState", and
having done that, why would you call it "State" in other functions?)

There are two major problems with your proposed rewrite:

(1) It isn't legal.  The conditions in 'if' expressions are
     *guards*, not expressions.  User defined function calls
     are not allowed at all in guards.

     If course, neither is the version with abstract patterns legal.
     One way to think of abstract patterns is that they are
     user-defined functions, but defined in such a very limited
     way that they are painfully obviously safe to call in guards
     without sacrificing any of the properties that distinguish
     guards from general expressions.  (And they do other things.)

(2) It would not, in general, work at all, even if user-defined
     functions *were* allowed in guards.  The reason is simple:
     your version absolutely depends on removing ANY old message
     from the mailbox and only later checking what you got.  But
     the abstract pattern approach satisfies what I take to be
     Ulf Wiger's requirement, namely that it is a *selective*
     receieve:  a message is ONLY removed from the mailbox if it
     matches some pattern.  Put another way, the selective
     receive with abstract patterns does not need the "X" case
     at the end.

There are also minor problems, such as calling
update(State, {data,Data}) instead of update(State, Data),
but they really don't matter.

The bottom line is that *selective* receives where multiple
pattern/guard matches are to be handled the same way warrants
*some* kind of special treatment, whether it is abstract patterns,
"decision tables", or some kind of multipattern extension,
because the choice of what to receive has to be done *in* the
receive.  Abstract patterns say "make your choice using
abstract patterns, moving the matching code out of the receive
and naming it".  Multipatterns say "make your choice using
multiple patterns confusingly interleaved with the actions."
The decision table approach says "the *choice* has to be made
inside the receive but the actions *don't*, so move the
actions out."

More information about the erlang-questions mailing list