Andrei Alexandrescu wrote:
Walter Bright wrote:
Daniel Keep wrote:
I need to know when that null gets stored, not when my code trips over
it and explodes later down the line.
Ok, I see the difference, but I've rarely had any trouble finding out
where the assignment happened. In fact, I can't remember ever having a
problem finding that.
That's because the null pointer exception is nearly always repeatable,
so it isn't hard to work backwards. The non-repeatable ones have been
due to memory corruption, which is a different issue entirely.
The world is more diverse than one environment. When I run 200 jobs on a
cluster, failure from null pointer usage comes back with no file and
line information, no debugger nicely starting, no nothing. And it's not
easy to reproduce that on a small machine with GUI and all.
Non-nullable types (or proxy struct or whatever) means the code won't
even compile if there's an untested path. And if we do try to assign a
null, we get an exception at THAT moment, so we can trace back to find
out where it came from.
Yes, I understand that detecting bugs at compile time is better. But
there's a downside to this. Every reference type will have two
subtypes - a nullable and a non-nullable. We already have const,
immutable and shared. Throwing another attribute into the mix is not
insignificant. Each one exponentially increases the combinations of
types, their conversions from one to the other, overloading rules, etc.
Andrei suggests making a library type work for this rather than a
language attribute, but it's still an extra thing that will have to be
specified everywhere where used.
There are a lot of optional attributes that can be applied to
reference types. At what point is the additional complexity not worth
the gain?
The added language complexity is very small and not visible to the user.
You change the default behavior. The library takes care of the rest.
Non-null is not const, not invariant, not shared, and should not be
compared in cost and benefits with them.
And there is no reference type with two subtypes. It's one type in the
language and one in the library. Maybe-null (the library) is a supertype
of non-null (the default).
One problem I can see is with extern(C),(Windows) functions, since
pointers are maybe-null in C. The name-mangling has to work out.
I can't see how this can be done without the compiler knowing SOMETHING
about both nullable and non-nullable types.
At the bare minimum, you need to deal with maybe-null returns and
reference parameters from C functions.
Incidentally, uses of maybe-null in immutable types must be _extremely_
rare. The usage statistics for D are likely to be skewed towards
non-null types, compared to Java. I'd say the 66% is a very conservative
lower bound.
Again: there is no "adding" to the language. It's changing. You don't
need to even look at overloading, combinations etc. All you need to look
at is constructors. (Oh, Bartosz and I found a couple of other bugs in
constructors last night too.)
Andrei