Do you remember the post I made about Truthy and Falsy back in December? How I said I understood it? What a sweet, naive child I was. It’s not like anything was wrong with that post, it’s just that there is so much more.
Here’s a little more of that iceberg.
A few months back, when I was learning Clojure, I came across some interesting information in the docs. Apparently when Clojure computes an
&& or an
|| statement, it doesn’t return
false, it returns one of the values in the statement. So it could be returning a string, or a number or a list or nil. So it could return
false too if that is one of the values. It kind of blew my mind. But it shouldn’t have.
One thing that languages that use the concept of “truthy” can do is take “boolean operators” like
or and just, not return booleans. What it does for
ands is that the language will return the first false if it’s false and the last true if it’s true. For
or it returns the first true if it’s true or the last false if it’s false. It makes sense when you break it down because it returns the last statement that it needs to evaluate. A lot of the time you can just ignore the fact that it returns these things. After all, if you extract the conditional into its own function, the value it returns is still going to have the truthy value you expect even if it’s a string or an array.
Here’s a simpler example in TypeScript with react. We’re seeing if a prop is there at all, and then the length of that prop
atLeastOneResponse = (): boolean => ( (this.props.form.responses && this.props.form.responses.length) )
The thing is, that’s going to start yelling.
this.props.form.responses can either be an array of strings or undefined, while both of those things can be falsy, neither can be false. And
this.props.form.responses.length can be a number (which can be falsy if it’s 0 or truthy otherwise) but it can’t ever be true or false. And the code says it returns a boolean so it’s sad that none of those returns are actually booleans. To fix it, we can use the double bang.
atLeastOneResponse = (): boolean => ( !!(this.props.form.responses && this.props.form.responses.length) )
The one thing about boolean operators in these circumstances, at least as I’ve seen so far is that while an
and or an
or doesn’t have to return a boolean,
not seems to always return a boolean. I can’t wait until I encounter a language where that’s not the case () but in the mean time, I’ll count on ![truthy value] to be false and a ![falsy value] to be true. Therefore !![truthy value] is going to be the boolean true. :tada:
But wait there’s more!
Here’s why I feel especially dense. I’ve known for about a year that you could do assignments like this in Ruby:
value = hash[:key] || "default” where if there’s no
:key key in
hash it’ll assign your variable
value it to the default. It was one of those fun facts that I just knew worked and didn’t think too hard about until I wrote it backwards by accident and realized the same “first truthy or last falsy” applied here too. It’s also why it’s “dangerous” to use it when the value of your key could potentially be
false because that would be evaluated the same as the
nil (aka falsy) it would return if there were no key that matched.
This means that kind of assignment can work in any language that follows this pattern. Whether or not it’s idiomatic or a bad idea for other reasons is still worth thinking about, but it’s always nice to know it’s an option. It’s also always nice to know why things work.