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