[eeps] Requests for comment on EEP 26 "Make andalso and orelse tail-recursive"

Bjorn Gustavsson <>
Fri Jan 30 15:11:01 CET 2009

On Fri, Jan 30, 2009 at 1:47 PM, Thomas Lindgren
<> wrote:
> (Erlang-questions removed from recipients.)
> --- On Fri, 1/30/09, Bjorn Gustavsson <> wrote:
>> From: Bjorn Gustavsson <>
>> Subject: Re: [eeps] Requests for comment on EEP 26 "Make andalso and orelse tail-recursive"
>> To: "Robert Virding" <>
>> Cc: , "Erlang Questions" <>
>> Date: Friday, January 30, 2009, 12:33 PM
>> On Fri, Jan 30, 2009 at 12:09 PM, Robert Virding
>> <> wrote:
>> > I support the EEP.
>> >
>> > What is the reason for not doing the full EEP-17? From
>> what I could see the
>> > difference was in using andalso and orelse in guards.
>> >
>> The difference was that EEP-17 suggested that ';'
>> and ',' should be allowed to
>> be used nested inside parenthesis, and that ';' and
>> 'orelse' should be
>> equivalent.
>> We want ';' to remain syntatic sugar for several
>> clauses with the same body,
>> that is
>> foo(Patterns) when P1; P2 ->
>>    Body.
>> works the same way as
>> foo(Patterns) when P1 ->
>>   Body;
>> foo(Patterns) when P2 ->
>>   Body.
>> If P1 causes an exception, but P2 evalutes to true, the
>> Body will be executed,
>> but in
>> foo(Patterns) when P1 orelse P2 ->
>>   Body.
>> the Body will not be executed if P1 causes an exception.
> This distinction seems far too fine to me, not to mention that it adds  complexity. Is it really necessary?
> My expectation would indeed be that 'orelse' behaved like ';' in the example above. It is based on the following reasoning:
> 1. An exception in an atomic guard expression A is considered a guard failure
> 2. For a guard expression (A orelse B), if A fails, then B will be run.
> Point 2 could be expressed more succinctly and declaratively by saying (A orelse B) succeeds if A succeeds or B succeeds, without specifying evaluation order, exception handling versus test failure or whatnot.

First note that this has nothing to do with EEP-26, as I intently
wanted to limit the scope to a single change
that is useful and would lead to minimal backward-compatibility problems.

Other changes to the guards is better suggested in a separate EEP.

The reason for the current behavior in guards is that we want
expressions such as

   foo(Term) when not element(3, Term) ->

to behave reasonably. If exceptions were to mean the same as false,
the guard would succeed
if the element/2 call failed (if Term is not a tuple with at least 3
elements). That does not seems right.
Also, if element(3, Term) returns something that is neither true nor
false, what should the result be?

(There are similar issues with the 'or' operator, while a false value
and failure have the same meaning
for the 'and' and ',' operators.)

To make everything consistent, we decided that failures and
non-booleans values in a context
where a boolean was expected should fail the guard, up to the next semicolon.

Also note that 'andalso'/'orelse' behave in the same way in guards and
function bodies. I am not sure how your
suggestion for 'andalso'/'orelse' should be implemented in bodies.
Should a failure on the left-hand
side of an 'andalso' cause an exception or not (as in a guard)?

To change that decision needs a new EEP and a thorough investigation
of the consequences for
backward compatibility.

You are welcome to continue the discussion, but please start a new thread.

Björn Gustavsson, Erlang/OTP, Ericsson AB

More information about the eeps mailing list