I'm reading some Clojure code at the moment that has a bunch of uninitialised values as nil
for a numeric value in a record that gets passed around.
Now lots of the Clojure libraries treat this as idiomatic. Which means that it is an accepted convention.
But it also leads to NullPointerException
, because not all the Clojure core functions can handle a nil
as input. (Nor should they).
Other languages have the concept of Maybe
or Option
to proxy the value in the event that it is null, as a way of mitigating the NullPointerException
risk. This is possible in Clojure - but not very common.
You can do some tricks with fnil
but it doesn't solve every problem.
Another alternative is simply to set the uninitialised value to a symbol like :empty-value
to force the user to handle this scenario explicitly in all the handling code. But this isn't really a big step-up from nil
- because you don't really discover all the scenarios (in other people's code) until run-time.
My question is: Is there an idiomatic alternative to nil-punning in Clojure?
Not sure if you've read this lispcast post on nil-punning
, but I do think it makes a pretty good case for why it's idiomatic and covers various important considerations that I didn't see mentioned in those other SO questions.
Basically, nil
is a first-class thing in clojure. Despite its inherent conventional meaning, it is a proper value, and can be treated as such in many contexts, and in a context-dependent way. This makes it more flexible and powerful than null
in the host language.
For example, something like this won't even compile in java:
if(null) {
....
}
Where as in clojure, (if nil ...)
will work just fine. So there are many situations where you can use nil safely. I'm yet to see a java codebase that isn't littered with code like if(foo != null) { ...
everywhere. Perhaps java 8's Optional
will change this.
I think where you can run into issues quite easily is in java interop scenarios where you are dealing with actual null
s. A good clojure wrapper library can also help shield you from this in many cases, and its one good reason to prefer one over direct java interop where possible.
In light of this, you may want to re-consider fighting this current. But since you are asking about alternatives, here's one I think is great: prismatic's schema. Schema has a Maybe
schema (and many other useful ones as well), and it works quite nicely in many scenarios. The library is quite popular and I have used it with success. FWIW, it is recommended in the recent clojure applied book.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With