Last week I wrote about some truthiness edge cases in JavaScript. This time, I have a quick tidbit on elegantly handling null/undefined values.
null
- called the "Billion-Dollar Mistake" by its inventor, C.A.R. Hoare - most programmers are probably intimately familiar with this (and why it might be categorized as a mistake!)
We've certainly all written some code like this:
if(foo != null) {
// Do something with foo
}
But, what if foo
is an object with multiple levels of nested objects? You'd probably agree that it gets a little cumbersome to write something like this:
if(foo != null) {
if(foo.bar != null) {
if(foo.bar.baz != null) {
// Now it's safe to use foo.bar.baz
}
}
}
Some more modern languages (Kotlin, JavaScript 2020, Swift, etc.) have support for what's known as "safe calls/optional chaining", and it looks like this:
x = foo?.bar?.baz?.doSomething()
The ?
indicates that the right-hand side should only be evaluated if the left-hand side is not null
. However, if any part of this expression is null
, then x
will be null
.
What if we wanted to specify what value x
should have in case any of the null
checks fail? We could obviously achieve this by checking if x
is null
after the statement and then assigning a different value to it, but if we wanted x
to be a constant, this would not be possible.
Some languages support a ternary operator, so you could do something like this:
x = foo?.bar?.baz ? foo?.bar?.baz?.doSomething() : <fallback value>
In my opinion, this is repetitive, and it's also error-prone - if doSomething()
returns null
, then x
could still be null
! You could work around this by putting ?.doSomething()
before the ?
of the ternary operator, but are we sure it's safe to call doSomething()
more than once? It could have side-effects that introduce subtle bugs into our code or be resource intensive and degrade our application's performance.
Instead, I'd like to propose a better way - the null(ish) coalescing operator:
x = foo?.bar?.baz?.doSomething() ?? <fallback value>
This way, x
can still be a constant, we'll catch any possible null
values in the entire chain, and we're only calling doSomething()
one time (at most).
Now, if you caught it, why did I call this the null*(ish)* coalescing operator? That's because in JavaScript, the optional chaining operator and null coalescing operator apply to BOTH null
and undefined
. Neat, huh?
I had known about this concept from working in Kotlin, where this functionality is called the "Elvis operator". It's written as ?:
- which looks a little bit like the top of Elvis' head (eyes & his signature curly hairdo) - plus, in the Kotlin community we can remember that anything that happens to the right of the operator is what occurs when "Elvis has left the building" (i.e. if you've encountered a null
and left the optional chain) And yes, I know - Programmers can be real nerds sometimes. ;-)
Now that I've been working in React Native using TypeScript (which is built on top of JavaScript), I discovered that this functionality also exists there. Which led me to discover that Swift has this same concept too - the "nil coalescing operator" (represented by ??
).
All of this to say - I think it's really exciting that more and more modern programming languages are converging and supporting ever more similar ways of writing code. Each language will always have its quirks (as well as advantages & drawbacks), but I think we're getting much closer to a world where Android developers can read through an iOS codebase and understand what's happening (not so back when they were still written in Objective C), or a traditional web developer can work on a mobile application (already a reality thanks to technologies such as React Native).
Know of other languages that support some variant of optional chaining/null coalescing? I'd love to hear from you in the comments!
Interested in working with me in the awesome Digital Products team here at Accenture? We're hiring mobile developers, web developers, and more!
Top comments (0)