I agree that null pointers are a bad idea and I try to avoid them in my code as often as possible. I go out of my way to avoid returning null to indicate an error condition. I use value types instead of reference types whenever possible, since a value type can't be null. Instead of using null to indicate an error condition, I use a second variable or throw an exception.
Just because your programming language supports null pointers, doesn't mean you need to use them. You can avoid the pitfalls discussed by Tony Hoare by simply refraining to use them. You will still need to handle null pointers coming into your code from outside, like from libraries, but your own code does not need to generate them.
Not sure if it is possible to have "only valid object exists, ever" and have it working for real. In pointers we have NULL to signal "not a pointer". In floats we have NAN to signal "not a number". In integers I miss not-an-integer enough that I often designate INT_MIN as not-an-integer representation. I notice when working with indices, index 0 is a convenient not-an-index value. Don't know enough theory to figure if this empirical anecdote amounts to something more than that.
The simple existence of "Not an object" value is fine. The abstraction built over the raw value should be good enough that it will confront you when you attempt to use it.
The next level is constructing types in a way that you can avoid such low level details of whether the pointer is valid.
In other words, encode the state in the type instead of a value that you need to test against every time you want to use it.
That's easier said than done, and it's not obvious how to do it with types.
Consider a non-blocking read. What the caller does depends on whether the read returns a value or "no data available". If the type of the object returned depends on whether there was a value, you just replaced a null check with a type check.
You can avoid that check with a caller with multiple return points and have the callee pick between them. Exceptions are the most obvious way to do that. However, exceptions happen immediately, while type/null checks can be done later.
Please, stop this nonsense. It is not as if the NULL/zero value was introduced after some code was written. This is a human written logic error, programmer(s) write logic and that logic will sometimes have bugs. This is someone getting paid to state an obvious fact and then throw philosophical phrases around in an attempt to sound like they are doing something. This is pure time wasted nonsense.
This reminds me of a microquest that I foolishly embarked on during COVID-19 lockdown:
There's no standard, widely-accepted way to unambiguously serialize and deserialize nulls within querystrings. JavaScript is perhaps one of the more frequent client languages for that, but Python and many other server-side languages are affected too. Could we do something about that?
On the other hand, having messages to nil do nothing in Objective-C had the interesting effect of making some iOS apps crash gradually rather than all at once. One might argue that it improved robustness in a strange way.
13 comments
[ 1.1 ms ] story [ 39.6 ms ] threadJust because your programming language supports null pointers, doesn't mean you need to use them. You can avoid the pitfalls discussed by Tony Hoare by simply refraining to use them. You will still need to handle null pointers coming into your code from outside, like from libraries, but your own code does not need to generate them.
The next level is constructing types in a way that you can avoid such low level details of whether the pointer is valid.
In other words, encode the state in the type instead of a value that you need to test against every time you want to use it.
Consider a non-blocking read. What the caller does depends on whether the read returns a value or "no data available". If the type of the object returned depends on whether there was a value, you just replaced a null check with a type check.
You can avoid that check with a caller with multiple return points and have the callee pick between them. Exceptions are the most obvious way to do that. However, exceptions happen immediately, while type/null checks can be done later.
There aren't many languages which support multiple continuations and SQL isn't one of them.
There's no standard, widely-accepted way to unambiguously serialize and deserialize nulls within querystrings. JavaScript is perhaps one of the more frequent client languages for that, but Python and many other server-side languages are affected too. Could we do something about that?
I liked the look of the proposal at https://github.com/whatwg/url/issues/469 that was working towards this.
In short, it provides the ability for "?a&b=" to represent the variable "a" containing null and "b" containing an empty-string.