Why not `and` -> `andalso` and `or` -> `orelse`

I always thought that Elixir would compile a and b into a andalso b (which I think is equivalent). To my surprise, Elixir compiles a and b into something like:

case _a@1 of
  false -> _b@1;
  true -> true;
  __@1 -> erlang:error({badbool, 'or', __@1})
end

Is here a reason for this that I don’t understand?

1 Like

@tmbb in what context? If it’s and inside guard clauses then IIRC it compiles to andalso. If it’s and in a module body then it does the case there as a short circuit.

I think that the code you showed is the code for a or b.

The Erlang compiler internally translates andalso and orelse to a case statement. Here is how the Erlang compiler internally translates an orelse:

case _a@1 of
  false -> _b@1;
  true -> true;
  __@1 -> erlang:error({badarg, __@1})
end

The only difference in the code is the code for generating the exception when the first operand is not a boolean. Elixir’s exception provides more information. I assume that’s why the Elixir compiler translates orelse itself instead of letting the Erlang compiler do it.

(Technical note: The Erlang compiler does this translation in the v3_core pass while translating to Core Erlang.)

10 Likes

I’m actually using erlang core (extracted from the Abst chunk of BEAM files), so this makes sense.