🤔 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!)

Want the latest Elixir Streams in your inbox?

    No spam. Unsubscribe any time.