[erlang-questions] eep: multiple patterns
Hynek Vychodil
vychodil.hynek@REDACTED
Mon May 26 19:15:10 CEST 2008
Thanks for very nice example.
On Mon, May 26, 2008 at 4:54 AM, Richard A. O'Keefe <ok@REDACTED>
wrote:
>
> On 23 May 2008, at 11:05 pm, Mats Cronqvist wrote:
>
> Hooray! Evidence!
> > let me assure you that there are major telecom equipment vendors
> > whose
> > code bases would benefit greatly from this syntax.
> > although i (no longer) has access to that code, the pattern appears
> > quite often in event-driven programming. here's a very small example
> > from a simple GUI application;
> >
> > loop(St) ->
> > receive
> > %% user deleted top window
> > {?MODULE,{signal,{window1,_}}} -> quit();
> > %% user selected quit menu item
> > {?MODULE,{signal,{quit1,_}}} -> quit();
> > %% user selected connect menu item
> > {?MODULE,{signal,{connect,_}}} -> loop(conn(St));
> > %% user selected disconnect menu item
> > {?MODULE,{signal,{disconnect,_}}} -> loop(disc(St));
> > %% user selected about menu item
> > {?MODULE,{signal,{about1,_}}} -> loop(show_about(St));
> > %% user clicked ok in about dialog
> > {?MODULE,{signal,{dialogb,_}}} -> loop(hide_about(St));
> > %% user deleted about dialog
> > {?MODULE,{signal,{dialog1,_}}} -> loop(hide_about(St));
> > %% we got data from the top_top process
> > {data,Data} -> loop(update(St,Data));
> > %% quit from the erlang shell
> > quit -> quit();
> > %% log other signals
> > X -> io:fwrite("got ~p~n",
> > [X]),loop(St)
> > end.
> >
>
> Let me start by making two changes to that code.
> The first is to indent it, so that I can read it.
> The second is to group together things with the same body.
>
> loop(St) ->
> receive
> quit ->
> %% quit from the Erlang shell
> quit()
> ; {?MODULE,{signal,{window1,_}}} ->
> %% User deleted top window.
> quit()
> ; {?MODULE,{signal,{quit1,_}}} ->
> %% User selected 'Quit' menu item.
> quit()
> ; {?MODULE,{signal,{connect,_}}} ->
> %% User selected 'Connect' menu item.
> loop(conn(St))
> ; {?MODULE,{signal,{disconnect,_}}} ->
> %% User selected 'Disconnect' menu item.
> loop(disc(St))
> ; {?MODULE,{signal,{about1,_}}} ->
> %% User selected 'About' menu item.
> loop(show_about(St))
> ; {?MODULE,{signal,{dialogb,_}}} ->
> %% User clicked 'OK' in "about" dialogue.
> loop(hide_about(St))
> ; {?MODULE,{signal,{dialog1,_}}} ->
> %% User deleted "about" dialogue.
> ; {data,Data} ->
> %% We got data from the top_top process.
> loop(update(St, Data))
> ; X ->
> %% Log other signals.
> io:fwrite("got ~p~n", [X]),
> loop(St)
> end.
>
> In this case, it matters that *every* message is to be received and
> acted on. That means that we can once again use the factorisation
> technique.
>
> loop(State) ->
> receive
> Message ->
> loop(State, classify(Message))
> end.
>
> classify(quit) -> quit;
> classify({?MODULE,{signal,{window1,_}}}) -> quit;
> classify({?MODULE,{signal,{quit1,_}}}) -> quit;
> classify({?MODULE,{signal,{connect,_}}}) -> connect;
> classify({?MODULE,{signal,{disconnect,_}}}) -> disconnect;
> classify({?MODULE,{signal,{about1,_}}}) -> show_about;
> classify({?MODULE,{signal,{dialog1,_}}}) -> hide_about;
> classify({?MODULE,{signal,{dialogb,_}}}) -> hide_about;
> classify({data,Data}) -> {data,Data};
> classify(X) -> {error,X}.
>
> loop(_, quit) ->
> quit();
> loop(State, connect) ->
> loop(conn(State));
> loop(State, disconnect) ->
> loop(disc(State));
> loop(State, show_about) ->
> loop(show_about(State));
> loop(State, hide_about) ->
> loop(hide_about(State));
> loop(State, {data,Data}) ->
> loop(update(State, Data));
> loop(State, {error,X}) ->
> io:fwrite("got ~p~n", [X]),
> loop(State).
>
> I like this because it makes a clean separation between
> "what are the actions" and "what are the names for the actions".
>
> Of course you can in-line this. Just as we can have
> case/case, we can have case/receive, getting
>
> loop(State) ->
> case receive
> quit -> quit
> ; {?MODULE,{signal,{window1,_}}} -> quit
> ; {?MODULE,{signal,{quit1,_}}} -> quit
> ; {?MODULE,{signal,{connect,_}}} -> connect
> ; {?MODULE,{signal,{disconnect,_}}} -> disconnect
> ; {?MODULE,{signal,{about1,_}}} -> show_about
> ; {?MODULE,{signal,{dialog1,_}}} -> hide_about
> ; {?MODULE,{signal,{dialogb,_}}} -> hide_about
> ; {data,Data} -> {data,Data}
> ; X -> {error,X}
> end
> of quit -> quit()
> ; connect -> loop(conn(State))
> ; disconnect -> loop(disc(State))
> ; show_about -> loop(show_about(State))
> ; hide_about -> loop(hide_about(State))
> ; {data,D} -> loop(update(State, D))
> ; {error,X} -> io:fwrite("got ~p~n", [X]),
> loop(State)
> end.
>
> Now my first reaction on seeing a whole raft of {?MODULE,{signal,
> {Foo,_}}}
> patterns was "this is too hard for me to read". I would be trying to
> simplify the protocol. Separating the receive protocol from the action
> selection makes this kind of maintenance easier. Inlining means that
> the versions with separate functions and with nested case/receive are
> operationally equivalent. A few hacks in the compiler could produce
> essentially the same code as the original version, although I doubt that
> it would be worth bothering.
>
> Tastes vary. To me, what we can write now in Erlang as it stands,
> separating "what are the actions" from "what are the names for the
> actions",
> is easier to read and understand than anything using multiple patterns
> would be, not because multiple patterns are a bad idea as such, but
> because
> combining multiple *complex* patterns into a single match makes the code
> harder to read. Multiple *simple* patterns might make for a more
> interesting example.
>
> --
> "I don't want to discuss evidence." -- Richard Dawkins, in an
> interview with Rupert Sheldrake. (Fortean times 232, p55.)
>
>
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions
>
--
--Hynek (Pichi) Vychodil
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080526/a0a93cbf/attachment.htm>
More information about the erlang-questions
mailing list