Null references (oh no, not again!)

Denis Koroskin 2korden at gmail.com
Wed Mar 4 03:35:16 PST 2009


On Wed, 04 Mar 2009 14:04:33 +0300, Walter Bright <newshound1 at digitalmars.com> 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.
>
>
>> 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?

Nullable types may and should be implemented as a library type, with a little of syntax sugar. Just the same as Object class.

Besides, I believe introducing non-nullables will make T.init feature obsolete, because you will have to initialize all the values explicitly thus solving one more problem - use of uninitialized value. This time - correctly.

And please don't tell me that T.init is a valid initializer and using it is fine and variable is not considered uninitialized anymore. It's a bad workaround that often doesn't work.

So essentially this is a feature swap: you add one and remove another.

Another question is the feature's usability. It might turn out to be not very handy to have all variables initialized, but we can't know until we really start using it, right?



More information about the Digitalmars-d mailing list