null references. We hate them, they make our programs exit in circumstances we didn't anticipate. Tony Hoare called them a "billion dollar mistake." I've spoken about this issue in this forum before, others have, we know this issue well.

TypeScript 2 and Swift, and some Java IDEs, implement a way of handling null references quite elegantly. I think we can learn from this.

The method of handling null in functional programming languages is to represent possibly null types with an Option monad. Accessing the references to the real values within usually requires applying pattern matching, or by calling different functions on Option/Maybe types for checking the references to see if they are null and getting them out again.

Other opinions may differ than this, but I think this method of handling the problem creates two issues.

1. Most languages (including D) do not support pattern matching. If pattern matching was added, it would be totally alien to any programmers coming from C, Java, JavaScript, Python, etc. This means this method of handling null might not be adopted. 2. Changing the access patterns when a type might possibly be null can confuse developers, and decreases the likelihood of adoption to fix what is a really essential issue in modern programming languages.

I believe the solution presented in TypeScript, in Swift (if you can find it in the documentation at all), and somewhat in some Java IDEs is much better, and much more familiar to most programmers. I'll explain by using T? to refer to possibly null types, and T for types which are not nullable.

As described above in the TypeScript blog, when you are handling a possibly null reference, assuming strict checking is turned on, you are forbidden from accessing any attributes or methods from that reference unless you first ensure that the reference is not null. To do this, you write an ordinary if statement or other Boolean expression. Within the confines of the area where you have checked for a null reference, if you say that the type is T?, the compiler knows that the type *must* be equivalent to T, as you have checked that the reference is not null.

Assignment of null to a type T is forbidden. Assignment to a type T? forms a fence, which would imply an atomic fence. When a type T is assigned to a variable of type T?, then after that line of code, the value can be considered to be of type T. When a type T? is re-assigned to a variable value, then the null safety checks will be applied again, and either another assignment expression or condition must be used before access is made.

In the case of TypeScript, you can also enforce access which might possibly crash your program if you really want to with x!.foo. (I personally wouldn't recommend ever doing this, but there might be some reason why it is needed.)

I say we could consider adopting such a method of handling null references in D. We could liberally assume for a time that any type T is non-nulllable, and apply checks only for T?, until we can change to some future version of D where T can never be null.

What does everyone think? Shall I write a DIP for this? Does everyone hate this idea and want to start hiring the hitmen to shoot me dead now?

As Andrei says, "Destroy!"

Reply via email to