[erlang-questions] if-elseif-else trick

Viktor Söderqvist viktor@REDACTED
Mon Feb 18 21:08:44 CET 2019


My example proved silly. Of course, normal 'if' is fine for guard
expressions and catch-all is to be avoided in general. I agree.

What I failed to mention was that you can use non-guard expressions with
this trick. (The trick's actually rewriting the elseifs to nested case.)

When using if with non-guard expressions, you need to evaluate them in
advance, which you may not want if these are side-effectful or just slow:

f() ->
    Cond1 = g1(),
    Cond2 = g2(),
    Cond3 = g3(),
    if Cond1 -> a;
       Cond2 -> b;
       Cond3 -> c;
       true  -> d

Therefore, you often see nested case expressions instead:

f() ->
    case g1() of
        true -> a;
        false ->
            case g2() of
                true -> b;
                false ->
                    case g3() of
                        true -> c;
                        false -> d

... or broken down into multiple functions:

f() ->
    case g1() of
        true -> a;
        false -> f2()
f2() ->
    %% You know

There's the throw style too, a slightly silly but a flat style:

f() ->
        g1() andalso throw(a);
        g2() andalso throw(b);
        g3() andalso throw(c);
        X -> X

The point of the ?elseif syntax trick is that it lets you write the
nested case above as the flat structure:

f() ->
    ?'if'(g1())   -> a;
    ?elseif(g2()) -> b;
    ?elseif(g3()) -> c;
    ?else         -> d.

You can even bind variables in the conditions if you would want that,
just to avoid deeply nested code. I would look more like perl than
erlang though, so don't do that.

>> That said...
>> The original premise of this thread is based on a misunderstanding of `if` and probably inexperience with `case`.
> Agreed

I agree too. :-) Thanks for clarifying!

Btw, I'm sorry for posting without having a real question. I just wanted
to show what can be done using a non-trivial parse transform.


More information about the erlang-questions mailing list