Elixir’s or
is Erlang’s orelse
. Erlang’s or
do not have Elixir equivalent.
Elixir’s or
is both erlang’s or
(kinda) and orelse
. Take a look
1 or 2
in normal context generates this code
case 1 do
false -> 2
true -> true
underscore -> :erlang.error({:badbool, :or, underscore})
end
And only in guards it translates to
:erlang.orelse(1, 2)
This is because orelse
will just err with badarg
, whereas in Elixir we want more accurate errors. But besides that this is the same behaviour as orelse
: only booleans on the left.
I would need to check, but I am pretty sure it will behave differently if one of the sides is not an boolean. As for example even with that code you cannot do something like foo == (a || b)
in guard.
Yeah, it has a problem with second and third case here. However, the first one works correctly. I think this is general problem of :erlang.orelse
which returns false
for :erlang.orelse(1, 2)
in guards.
case 1 do
x when x == (1 ||| 2) -> true
_ -> false
end
|> IO.inspect()
case 1 do
x when x == (nil ||| 1) -> true
_ -> false
end
|> IO.inspect()
case 1 do
x when x == (false ||| 1) -> true
_ -> false
end
|> IO.inspect()
It does not return false
for :erlang.orelse(1, 2)
. It fails. There is huge difference between these two:
defmodule Foo do
def f(a) when (a or false) or true, do: :matched
def f(_), do: :not_matched
def g(a)
when a or false
when true, do: :matched
def g(_), do: :not_matched
end
Foo.f(nil) # => :not_matched
Foo.f(false) # => :matched
Foo.g(nil) # => :matched
Foo.g(false) # => :matched
Yeah, you’re right