+1 Yep<br><br><div class="gmail_quote">On Fri, Feb 20, 2009 at 12:53 AM, Richard O'Keefe <span dir="ltr"><<a href="mailto:ok@cs.otago.ac.nz">ok@cs.otago.ac.nz</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d"><br>
On 20 Feb 2009, at 9:22 am, Zvi wrote:<br>
><br>
><br>
> fess-3 wrote:<br>
>><br>
>> ...<br>
>> floating guards on the LHS of a match seem like they could make<br>
>> code much more concise and readable, and erlang-like [ to me ]<br>
>><br>
>><br>
>>   { X when is_integer(X), [ "x" | Rest ] } = string:to_integer(Str),<br>
>>   { Y when is_integer(Y), _ } = string:to_integer(Rest),<br>
>><br>
><br>
> much more readable, if we can marry patterns with guards:<br>
><br>
>   { X = int(), [ "x" | Rest ] } = string:to_integer(Str),<br>
>   { Y = int(), _ } = string:to_integer(Rest),<br>
><br>
> where int() is patten matching any integer value.<br>
<br>
</div>int() would be a function call, which doesn't make much sense<br>
in a guard.<br>
<br>
This is a rather interesting example, because<br>
  - string:to_integer/1 and string:to_float/1<br>
    ARE in the on-line documentation<br>
  - they ARE accepted by 'erl'<br>
  - but they are NOT in lib/stdlib/src/string.erl<br>
They both return either {Number,Tail} or {error,Cause}.<br>
<br>
I have to say that this interface is brain-dead.<br>
When a function can return one of several outcomes,<br>
it should be possible to tell one from another by a simple<br>
pattern match.  A *good* result would be<br>
        {ok,Number,Tail}<br>
or      {error,Cause}<br>
<br>
The solution is not to bloat the pattern sublanguage beyond<br>
all recognition, but to fix the broken interface.<br>
<br>
better_to_integer(String) -><br>
     case string:to_integer(String)<br>
       of {error,Cause} -> {error,Cause}<br>
        ; {Number,Tail} -> {ok, Number,Tail}<br>
     end.<br>
<br>
better_to_float(String) -><br>
     case string:to_float(String)<br>
       of {error,Cause} -> {error,Cause}<br>
        ; {Number,Tail} -> {ok,Number,Tail}<br>
     end.<br>
<br>
and then to write a plain<br>
<br>
        {ok,X,[$x|Rest]} = better_to_integer(Str),<br>
        {ok,Y,_        } = better_to_integer(Rest)<br>
<br>
Testing whether X or Y is an integer ASKS THE WRONG QUESTION.<br>
A better question is "is this not the atom 'error'"?<br>
But the best question is the one we really want: "is this<br>
conversion ok?"  And fixing the interface lets us ask very<br>
simply what we really mean.<br>
<br>
There's a common pattern I'm seeing in discussions like this.<br>
There is some ugly code, but people accept the *cause* of the<br>
ugliness and just want to put a glossy coat of paint over<br>
the *symptoms*.<br>
<br>
It's a basic principle of good data structure design in Prolog,<br>
which has carried over without change to Erlang, that when a<br>
data structure could be one of several alternatives, you<br>
should be able to recognise each of the alternatives with a<br>
single *positive* pattern match.  (That is, nothing should<br>
be recognised by virtue of not being something else.)  When I<br>
reimplemented the internal data structures of the Quintus<br>
Prolog compiler to follow this principle, not only was the<br>
code easier to read, the compiler ran 20% faster.<br>
<div class="Ih2E3d"><br>
> Or, if X and Y unused, like in the example above:<br>
><br>
>   { int(), [ "x" | Rest ] } = string:to_integer(Str),<br>
>   { int(), _ } = string:to_integer(Rest),<br>
<br>
</div>It's *still* better to write<br>
<br>
     {ok,_,[$x|Rest]} = better_to_integer(Str),<br>
     {ok,_,_        } = better_to_integer(Rest)<br>
<br>
By the way, the pattern ["x"|Rest] should be<br>
[$x|Rest] as I have it, or "x"++Rest.<br>
<div><div></div><div class="Wj3C7c"><br>
<br>
_______________________________________________<br>
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<br><br>Analyze your data in minutes. Share your insights instantly. Thrill your boss.  Be a data hero!<br>Try Good Data now for free: <a href="http://www.gooddata.com">www.gooddata.com</a><br>