DEV Community

BigSpaces
BigSpaces

Posted on

Truthy, Falsy, Confusy

It is 5:24am - I have been up since 2am (this is not me at all) - I've already had TWO coffees.

Given those attenuating circumstances I take no responsibility for what is coming. Read at your own risk :)

My goal is to understand the logic of the comparison operator "&&"

First, my brothers and sisters, we need a firm grasp of the concepts "truthy" and "falsy".

That one is easy. It is just a brain tatoo. The values "nil" and "false" are falsy. Everything else is truthy.

It feels like a dogma to me and it is better if I do not fall into the rabbit hole of trying to get it. Just have faith: Everything in the Elixir universe is truthy but "false" and "nil". We do not ask questions... yet.

Now that we are believers, my next step is trying to get into the mind of whoever invented the "&&" as a comparison operator.

Such mind came up with "if left is truthy then right and if left is falsy then left"

In other words, "&&" does not give an atom about the right, just the left... unless it has to return the right, based on what is on the left, right?

You may ask "why such logic?", and I repeat: we do not ask questions. Drink the Elixir. At least that is why I am doing.

Image description

So to drill it down:

"Ex-girlfriend" && "My dog" should return "My dog"
False && "My dog" should return false
Nil && "My ex-girlfriend" should return nil

And that is correct.

Just for reference's sake... behold my dog, who now lives with my ex-girlfriend. He is bound to her, and she shall not return him, and that shall not change. That is called immutability.

But I digress.

Image description

Now I need to tatoo the logic behind "||", which is easier: "Return the first truthy value."

Of course I had to try what happens should both values be falsy. Here it goes:

false || false returns false (no shock there)
nil || nil returns nil (so far so good)
nil || false returns false (interesting)
false || nil returns nil (why? who knows!)

From this I draw two conclusions:

  1. My life is very, very sad.
  2. It seems that ||, unlike &&, does have a bit of a preference for what is on the right. Why? Mysteries keep piling up. José, where are you?

I need to get to the end of this... please indulge me. So:

"My dog" || nil returns "My Dog"
false || "My dog" returns My Dog
"My ex-girlfriend" || "My dog" returns My ex-girlfriend (we don't want that returned).
"My dog" || "My ex-girlfriend" returns "My dog" (she ain't returning him. Immutability).

If I want to keep retrieving my dog, I have two options now:

"My dog" || "My ex-girlfriend" (because || is first truthy value)
"My ex-girlfriend" && "My dog" (because && is if left is truthy then right)

5:57am

And now for the final shebang. What do we make of this expression? What should it return?

"this" == "this" && "The Same" || "Not The Same"

I see that Elixir breaks it down, though a million times faster than me (it is only taking me a week to get this one). I assume Elixir reads from left to right, though I am not sure what is going on under the hood. But, what I know is...

"this" == "this" is true

so

true && "The Same" (if left is truthy then right, so right: The Same)

so

"The Same" || "Not The Same" (first truthy value)

Returns "The Same". Turns out that "this" and "this" are "The Same".

Image description

We need to finish this. We do. Let's try changing one value.

"This" == "That" && "The Same" || "Not The Same"

False && "The Same" (if left is falsy then left, so false)

False || "Not The Same" (first truthy value, so "Not The Same")

Turns out that "This" is "Not The Same" as "That".

I wish I could tell you that I have it. I do not. But I am one step closer... Not too sure closer to what, actually. Elixir mastery? Needing therapy? Both?

I take solace in knowing that, despite my brain having a few thousand braincells less, my dog is actually very happy living with my ex-girlfriend, I am very happy living without my ex-girlfriend, and we are both very happy about all of that. In good terms.

(I had to clarify that, for the record.)

If you are at all attracted to seeing yourself in the same type of mental stretch that enticed me to write this blog post, and reach the same pinnacle of Elixir wisdom that I am displaying lately, I could put you in touch with my superhero mentor. You can tell my brain is doing push-ups, and sweating buckets.

You see... he thought I was capable of solving the following exercise:

Image description

I wasn't. Hence the mental stretch, the post, and two coffees :)

Gladly, a companion on the path with more knowledge (and possibly a more rested brain than mine), came up to the rescue, replacing dogs, ex-girlfriends and wordy confusing things with numbers.

So, for the number-oriented, here is another way to look at the same conundrum.

iex(1)> 1 == 2 && 3 || 4
4
Enter fullscreen mode Exit fullscreen mode

All we are doing is recreating an if expression!

iex(2)> if 1 == 2 do
...(2)>   3
...(2)> else
...(2)>   4
...(2)> end
4
Enter fullscreen mode Exit fullscreen mode

Thank you, @czrpb, for that.

git add .
git committ -m "I will get this. No matter how long it takes me"
Enter fullscreen mode Exit fullscreen mode

BigSpaces

Top comments (2)

Collapse
 
brooklinmyers profile image
Brooklin Myers

I continue to adore your writing. Can't wait to meet this superhero mentor of yours ;) He'd probably explain this better than I will.

To answer your question. "Why does this return nil"

false || nil
Enter fullscreen mode Exit fullscreen mode

|| returns the first truthy value. In most cases this "mental model" is sufficient.
You've uncovered a case where the simplification breaks.

step1: It first checks false -> NOPE
step2: it then checks nil -> NOPE
step3: we've checked all values. There was no truthy value, so just return whatever falsy value we're "looking" at.

nil is the last value. There was no truthy value, so we return the last falsy value. In 99.99 percent of use cases this won't matter, but it's an interesting quirk that you've uncovered.

Have you ever heard of Pareto Principle (Also called the 80/20 rule)? Essentially, 20% of our input tends to create 80% of our output. Memorizing edge-cases like this is likely to cause cognitive overload. Consider focusing on the 20% of Elixir that will let you solve 80% of problems.

Collapse
 
bigspaces profile image
BigSpaces • Edited

Thank you for your reply, Brook. Happy to introduce you to my superhero mentor anytime you have a mirror handy ;)

I find that part of my learning happens when I uncover the underlying principles that inform the rest of "how the machine works". Finding those edge-cases are not important, I agree, but it is part of how I break things into pieces to see their insides and hopefully learn something. Granted, it is not very practical, but sometimes a lightbulb goes on.

This reminds me of how I learnt MS-DOS. I used to tinker with the computer while my dad was at work, and more often than not I would break something. I was forced to find a solution before dad returned from work as to avoid any trouble. Part of that spirit is still there: "what happens if I do THIS? Oooops! Time to learn FAST and fix this thing!".

Also, in my defense, I experienced insomina that night, had two coffees, and my mind was all over the place :D On my day to day I am way more pragmatic with the use of my study time :)

Thank you for explaining the quirk! We continue!!