[erlang-questions] The If expression
Thu Jan 1 21:14:46 CET 2009
I would like to hear your views and proposals for an alternative
syntax for the 'if' expression. If the majority thinks that the result
of the discussion in this thread is interesting enough I will sum it
up and submit it as an Erlang Enhancement Proposal.
The background is the intensive discussion on this mailing list back
in March. There has also been quite a number of questions to the
mailing list on how to use the 'if'-expression, generally leading to a
recommendation to use the 'case'-expression instead of 'if'. Some have
even argued that the 'if' expression should be retired/obsoleted since
it is useless in its current form. I find myself almost never ever
using the 'if'-expression due to the limitations listed below. At the
same time I feel that the 'case'-expression is to "heavy-weight" or
clumsy when used for branching on bools.
Today an 'if'-expression is defined as:
if GuardSeq1 -> Body1;
GuardSeqN -> BodyN
With the added (undocumented?) twist that if a guard throws an
exception the guard simply evaluates to false.
In addition to the above (which is kept for backwards compatibility) I
suggest adding an alternative form with the following syntax:
if Expression -> Body else -> ElseBody end
which should act as syntactical sugar for the more clumsy and unintuitive:
case Expression of
true -> Body;
_Else -> ElseBody
My hope is that with this improvement 'if'-statements would be the
recommended choice for expressions evaluating to a bool() and
'case'-statements the natural choice for all other expressions. This
proposal is in no way competing with other recently proposed control
flow improvements, such as using the already reserved word 'cond' and
"unnesting case statements".
I think this would be rather simple to implement. I believe it could
for instance be done with just a 4-5 lines in the parser. It would
also be "almost 100%" backwards compatible ('else' would need to
become a reserved word, but this could very well be needed already by
earlier enhancement proposals, e.g. by EEP-25).
The proposal would address two of the problems with the current syntax:
1. Today only guards are allowed, not full expressions. For instance,
today it is NOT ok to write:
if erlang:system_info(smp_support) -> init_smp();
true -> init()
which many believe is a rather serious limitation of the usefulness.
2. At least of of the guards have to evaluate to true, otherwise a
runtime error will occur. This leads to unintuitive constructs like:
if Bool -> do_true();
true -> do_false() end.
Which could be replaced by a more intuitive:
if Bool -> do_true() else -> do_false() end.
An open question is if it should also be allowed to have expressions
without an 'else' clause, as proposed by Damien Katz, i.e.:
if Expression -> Body end
Which might be useful in some cases, e.g.
if Logging -> log:write("Aiee") end,
This could be handled by introducing a default return value for the
else clause in the odd cases where we might sometimes care about the
value of the "if"-expression, i.e.:
LoggingSucceded = if Logging -> log:write("Aiee") end
In this particular case returning false might seem like a good idea,
but in other cases e.g. an empty list might be just as natural. I am
just not sure how to apply the rule of least surprise to this...
Another proposal might be to allow "if"-expressions without an else
clause only when it is obvious to the compiler that the return value
will be discarded. The second example would thus result in a
"LoggingSucceded is unsafe in 'if' (line x)" error when compiling
(similar to what exists for e.g. case clauses today).
More information about the erlang-questions