[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