null analysis with control flow

w0rp via Digitalmars-d digitalmars-d at puremagic.com
Wed Sep 21 06:10:53 PDT 2016


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.

https://blogs.msdn.microsoft.com/typescript/2016/07/11/announcing-typescript-2-0-beta/

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!"


More information about the Digitalmars-d mailing list