[erlang-questions] style question - best way to test multiple non-guard conditions sequentially

Jonathan Leivent jleivent@REDACTED
Thu Jun 20 17:29:40 CEST 2013


On 06/19/2013 10:15 PM, Richard A. O'Keefe wrote:
>
> On 20/06/2013, at 6:23 AM, Jonathan Leivent wrote:
>
>> Suppose one has multiple conditions that are not guards that need to be tested sequentially (meaning, only test condition N+1 after condition N tests false) in a function.
>
> Ah hah!  You want the long-ago-proposed 'cond' form.
>
> pick([{Test,Act}|Rest]) ->
>      case Test()
>        of true  -> Act()
>         ; false -> f(Rest)
>      end.
>> fun(...) ->
>>   C1 = cond1(...),
>>   C2 = C1 orelse cond2(...),
>>   C3 = C2 orelse cond3(...),
>>   if C1 -> ...;
>>      C2 -> ...;
>>      C3 -> ...;
>>      true -> ...
>>   end.
>
> fun(...) ->
>      pick([
>          {fun () -> cond1... end,
>           fun () -> action1... end},
>          {fun () -> cond2... end,
>           fun () -> action2... end},
>          {fun () -> cond3... end,
>           fun () -> action3... end},
>          {fun () -> true end,
>           fun () -> action4... end}).
>
> Choose your own name for this.

I was hoping for something that more syntactically resembles a classic 
if/elsif/else block.  Without closures.

I started playing with some macros, and came up with this:

-define(IF(C), try (C) andalso begin).
-define(ELSIF(C), true end orelse (C) andalso begin).
-define(ELSE, true end orelse begin).
-define(ENDIF, true end catch {if_result, IF_RESULT} -> IF_RESULT end).
-define(BREAK(R), throw({if_result, R})).

foo(X) ->
         ?IF(cond1(X))
             expr1,
             expr2,
             ?BREAK(expr3),
         ?ELSIF(cond2(X))
             expr4,
             expr5,
             ?BREAK(expr6),
         ?ELSIF(cond3(X))
             expr7,
             expr8,
             ?BREAK(expr9),
         ?ELSE
             expr0,
             expra,
             ?BREAK(exprb),
         ?ENDIF.

One downside is that emacs isn't smart enough to indent this correctly, 
since it doesn't expand macros.  Also, to play better with other things, 
including other such ?IF statements in the same scope, the ?ENDIF macro 
shouldn't bind a variable - but I haven't figured out how to make that 
not happen.

>
> However, I cannot help feeling that in each specific instance
> of this there would be something better to write instead.  So
> how about showing us a real example?

Anything that would have worked in an if statement were the conditions 
just guards.  In the case I'm interested in, the conditions are 
predicates on an opaque type - so they can't be guards.

>>
>> I guess this also implies the question: why does Erlang require the conditions in an if statement to be guards?
>
> Because back when Erlang was invented, there were no conditions that
> were not guard tests *only*.  For example, X > Y was not an expression.
> There were no andalso or orelse.

OK - I will then add a word to the above question: why does Erlang 
*still* require the conditions in an if statement to be guards?

How hard is it to remove this restriction?

-- Jonathan




More information about the erlang-questions mailing list