K. Sabbak


And Or What?

August 03, 2018

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 true or 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 true or 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 and and 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.

Now, for some reason, I took this as a cool Clojure thing and moved on with my life until I ran across it in TypeScript. Now since TypeScript is a statically typed JavaScript (give or take), it does a lot of what JS does. I hadn’t realized that JS did the same thing* with its boolean operators. I realized this when I tried to pull a lengthy conditional into its own named function for clarity and TypeScript yelled at me becaues the return values couldn’t be converted to a boolean.

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.

*Truthy in JavaScript is a party. And by party, I mean it has no coherent rules. Empty objects and arrays are truthy but an empty string is falsy. ¯\_(ツ)_/¯

Tags: pairing