[erlang-questions] Erlang elseif

damien morton <>
Fri Nov 21 10:38:28 CET 2008


expressionX are constrained to be guard expressions, not user defined functions.

On Fri, Nov 21, 2008 at 6:59 PM, Joseph Wayne Norton
<> wrote:
>
> Daniel -
>
> You can implement
>
>   If <expression1> == true then <result1>
>   elseif <expression2> then <result2>
>   else <result3>
>
> in erlang as follows
>
> if <expresson1> == true ->
>     <result1>;
>    <expression2> ->
>     <result2>;
>    true ->
>     <result3>
> end.
>
>
>
> On Fri, 21 Nov 2008 16:37:59 +0900, Daniel Rönnqvist
> <> wrote:
>
>> I am merely trying to figure out why this simple logical control
>> structure
>> don't exist;
>>
>> If <expression> == true then <expression>
>> elseif <expression> then <expression>
>> else <expression>
>>
>> I know I can get lots and lots of good ideas on how to do this if I were
>> to
>> give you my whole real example but that is not my point. I am narrowing
>> it
>> down to this because THIS is what I want to discuss.
>>
>> IMHO, it shouldn't be that hard for the compiler/precompiler to "rewrite"
>> another control structure as nested case statements which would work as a
>> general solution, be very fast with less and arguably more readable code.
>>
>> BR,
>> Daniel Rönnqvist
>>
>> 2008/11/21 Richard O'Keefe <>
>>
>>> >> this but I could not find anything that answered my question. The
>>> >> thing is
>>> >> that I want a general way to branch the execution of my code based
>>> >> on the
>>> >> result on an expression. Very similar to how if works but I want to
>>> >> be able
>>> >> to test expressions and not only guards. If you're thinking "then
>>> >> you have
>>> >> case" now look below at function elseif2() and you'll see my point.
>>>
>>> Given that we have length(List) in guards, which definitely breaks
>>> the "guards are fast" guideline, it would be tempting to allow
>>> member(Term, List) in guards as well.
>>> >> 42> e:elseif4($Q).
>>> >> Member of capital
>>> >>
>>> >> -define(CAPS, "QWERTY").
>>> >> -define(SMALL, "qwerty").
>>> >> -define(NUMS, "123456").
>>> >>
>>> >> %% The wierd not-so-Erlang way
>>> >> elseif1(A) ->
>>> >>   lists:member(A,?CAPS)
>>> >>       andalso begin
>>> >>                   io:format("Member of capital\n"),
>>> >>                   true
>>> >>               end
>>> >>       orelse
>>> >>       lists:member(A,?SMALL)
>>> >>       andalso begin
>>> >>                   io:format("Member of small\n"),
>>> >>                   true
>>> >>               end
>>> >>       orelse
>>> >>       lists:member(A,?NUMS)
>>> >>       andalso begin
>>> >>                   io:format("Member of nums\n"),
>>> >>                   true
>>> >>               end
>>> >>       orelse
>>> >>       io:format("Not a member").
>>>
>>>         ei(Letter) when is_integer(C) ->
>>>            io:format(eic(Letter)).
>>>
>>>        eic(C) when C == $Q ; C == $W ; C == $E
>>>                   ; C == $R ; C == $T ; C == $Y
>>>            -> "Member of capital\n";
>>>        eic(C) when C == $q ; C == $w ; C == $e
>>>                  ; C == $r ; C == $t ; C == $y
>>>            -> "Member of small\n";
>>>        eic(C) when C == $1 ; C == $2 ; C == $3
>>>                  ; C == $4 ; C == $5 ; C == $6
>>>            -> "Member of nums\n";
>>>        eic(_)
>>>            -> "Not a member\n".
>>>
>>> In fact, I'd probably do it with two tables:
>>>
>>>        ei(Letter) -> io:format(eim(eic(Letter))).
>>>
>>>        eic($Q) -> large;
>>>        eic($W) -> large;
>>>        eic($E) -> large;
>>>        eic($R) -> large;
>>>        eic($T) -> large;
>>>        eic($Y) -> large;
>>>        eic($q) -> small;
>>>        eic($w) -> small;
>>>        eic($e) -> small;
>>>        eic($r) -> small;
>>>        eic($t) -> small;
>>>        eic($y) -> small;
>>>        eic($0) -> digit;
>>>        eic($1) -> digit;
>>>        eic($2) -> digit;
>>>        eic($3) -> digit;
>>>        eic($4) -> digit;
>>>        eic($5) -> digit;
>>>        eic($6) -> digit;
>>>        eic(_)  -> other.
>>>
>>>        eim(large) -> "Member of capital\n";
>>>        eim(small) -> "Member of small\n";
>>>        eim(digit) -> "Member of nums\n";
>>>        eim(other) -> "Not a member\n".
>>>
>>> I know the table is large, but if you want to classify this way
>>> here, you may well want to classify the same way somewhere else.
>>> I like this approach a lot: it's dead simple and it's fast.
>>>
>>> Let's look at the pure 'case' version:
>>>
>>>        ei(A) ->
>>>            M = case lists:member(A, ?CAPS)
>>>                  of true -> "Member of capital\n"
>>>                    ; false ->
>>>                     case lists:member(A, ?SMALL)
>>>                        of true -> "Member of small\n"
>>>                          ; false ->
>>>                          case lists:member(A, ?NUMS)
>>>                             of true -> "Member of nums"
>>>                             ; false -> "Not a member\n"
>>>                          end
>>>                     end
>>>                end,
>>>            io:format(M).
>>>
>>> Suppose the syntax were extended ever-so-slightly to
>>> include an equivalent of Algol 68's "ouse":
>>>
>>>        ei(A) ->
>>>            M = case lists:member(A, ?CAPS)
>>>                  of true -> "Member of capital\n";
>>>             or case lists:member(A, ?SMALL)
>>>                  of true -> "Member of small\n";
>>>             or case lists:member(A, ?NUMS)
>>>                  of true -> "Member of nums\n"
>>>                   ; false-> "Not a member"
>>>                end,
>>>            io:format(M).
>>>
>>> Here the sequence "; or case" is equivalent to
>>> "; _ -> case" PLUS an extra "end" at the end.
>>>
>>> Now do
>>>        -define(IF, case).
>>>        -define(THEN, of true ->).
>>>        -define(ELIF, ; or case).
>>>        -define(ELSE, ; false ->).
>>>        -define(END, end).
>>> and
>>>
>>>        ei(A) ->
>>>            M = ?IF   lists:member(A, ?CAPS)  ?THEN "Member of capital\n"
>>>                ?ELIF lists:member(A, ?SMALL) ?THEN "Member of small\n"
>>>                ?ELIF lists:member(A, ?NUMS)  ?THEN "Member of nums\n"
>>>                ?ELSE                               "Not a member"
>>>                ?END,
>>>            io:format(M).
>>>
>>> I'm not actually advocating the use of ?IF, ?THEN, ?ELIF, ?ELSE, ?END;
>>> I mention them merely to clarify that the "ouse" approach gives you
>>> something structurally similar to if-then-elif-else.
>>> I _do_ think that something along the lines of "; or case" would be
>>> nice, but as it stands it would be far too error-prone.
>>>
>>> Every time something like this comes up I say the same thing:
>>>
>>>        Show us some real code, not a toy example.
>>>
>>> With real code, there is almost always a better way.
>>>
>>>
>>> _______________________________________________
>>> erlang-questions mailing list
>>> 
>>> http://www.erlang.org/mailman/listinfo/erlang-questions
>>>
>
>
>
> --
> 
> _______________________________________________
> erlang-questions mailing list
> 
> http://www.erlang.org/mailman/listinfo/erlang-questions



More information about the erlang-questions mailing list