🤔 and/or Vs. &&/||. Which to use?
Notes
When people come to Elixir, I often hear them ask which they should use:
and
/or
OR &&
/||
?
Though they’re similar in many ways, they’re not the same! Here are some useful differences and some pitfalls.
Truthy and falsey
First, &&
and ||
compare truthiness and falsyness. Falsy values include
nil
and false
. Everything else is truthy (including things like ""
,
"false"
, etc.)
Because of that, &&
and ||
can be helpful as short-circuit operators.
For example, we may want to get a value result
(say, from a function) but use
a default value if the return value is nil
:
result = nil
result || "default"
# => "default"
result = "hello world"
result || "default"
# => "hello world"
Or we may only want to evaluate an expensive operation if some condition is truthy first:
result = nil
result && dbg("expensive operation here")
# => nil (i.e. expensive operation never ran)
result = "go for it"
result && dbg("expensive operation here")
# dbg output: "expensive operation here"
# => "go for it"
Dangers
But there are dangers to using those comparisons. An example comes when we use
them around System.get_env/1
:
staging = System.get_env("STAGING")
staging && this_should_not_run_in_prod()
The problem comes because System.get_env/1
returns strings. So when we have
STAGING=false
, System.get_env("STAGING")
returns "false"
(which is
truthy):
staging = System.get_env("STAGING")
# => "false"
staging && this_should_not_run_in_prod()
# => this_should_not_run_in_prod() runs in production!
That would not happen if we use and
:
staging = System.get_env("STAGING")
# => "false"
staging and this_should_not_run_in_prod()
** (BadBooleanError) expected a boolean on left-side of "and", got: "false"
As you can see, and
expects a boolean and raises if the left-hand side isn’t
one.
So, when you know you need to have booleans (or whenever you can constrain the
comparison to booleans), use and
and or
. And if you know you’re expecting
truthy/falsey values, use &&
and ||
.
NOTE: in the video, I say that and
and or
need booleans on both sides.
That’s not true. They only need them on the left-hand side.
In that way, they can work like short-circuits too: true and 24
gives us 24
and false or 23
gives us 23
. (Thanks to James Edward Gray II for pointing
that out!)