Reputation: 5709
Can someone please help explain why we get the argument error? Are we not supposed to check for truthyness this way? On Elixir 1.3
iex(1)> true and true
true
iex(2)> "true"
"true"
iex(3)> true
true
iex(4)> true and "true"
"true"
iex(5)> "true" and true
** (ArgumentError) argument error: "true"
Upvotes: 4
Views: 5503
Reputation: 41527
Elixir has two sets of boolean operators:
or
, and
and not
in principle require their arguments to be actual booleans, i.e. the atoms true
and false
||
, &&
and !
accept arguments of any types, and check "truthiness".Though in fact, or
and and
only check the type of the first argument. For any value of x
, the expressions false or x
and true and x
will simply return x
. This might seem confusing, but it allows using or
and and
as the last expression in a recursive function without impeding tail recursion. For example, consider this function, which checks whether all elements in a list are equal to 42:
def x([]) do
true
end
def x([h|t]) do
h == 42 and x(t)
end
Because and
permits tail recursion, this function will run in constant stack space. If and
would check the type of its second argument, the function would have to make a normal call one stack frame "deeper", and upon return perform the check and return the value.
Upvotes: 5
Reputation: 11278
The "wordy" boolean operators - and
, or
and not
are strict - they expect all values to be strictly boolean. The symbolic operators - &&
, ||
and !
- operate on the "truthiness" instead of strict booleans.
Because all booleans operators are short-circuiting they will actually only check the first argument for being strictly boolean, but I discourage using them with non-booleans.
Upvotes: 2
Reputation: 15736
From the docs:
Elixir also provides three boolean operators: or, and and not. These operators are strict in the sense that they expect a boolean (true or false) as their first argument:
iex> true and true true iex> false or is_atom(:example) true
Providing a non-boolean will raise an exception:
iex> 1 and true ** (ArgumentError) argument error: 1
So that's to answer why it raises.
In order to do what you want, you need to use the &&
operator, so it would be
"true" && true
and again, a quote from the docs:
Besides these boolean operators, Elixir also provides ||, && and ! which accept arguments of any type. For these operators, all values except false and nil will evaluate to true:
# and iex> nil && 13 nil iex> true && 17 17
Upvotes: 0