Non-nullable references, again

Don nospam at nospam.com
Wed Dec 31 07:29:33 PST 2008


Denis Koroskin wrote:
> On Wed, 31 Dec 2008 08:37:56 +0300, Daniel Keep 
> <daniel.keep.lists at gmail.com> wrote:
> 
>>
>>
>> dsimcha wrote:
>>>>> 50% of the bugs that people run into today, coding with C# in our
>>>>> platform, and the same is true of Java for that matter, are probably
>>>>> null reference exceptions.
>>>  Yes, but even if this is accurate, it's misleading.  Very seldom are 
>>> null
>>> references difficult-to-find, time-consuming bugs.  Most other things 
>>> in D and
>>> other languages that are designed to prevent specific classes of bugs 
>>> are designed
>>> to prevent extremely aggravating, hard to track down bugs.
>>>  For example, GC was invented because tracking down memory leaks is a 
>>> huge PITA.
>>> Bounds checking was invented because off-by-one errors can be subtle 
>>> and hard to
>>> find.  Null reference errors, on the other hand, manifest themselves 
>>> in a
>>> predictable way (segfaults), and if you're using the safe memory 
>>> model, i.e.
>>> bounds checking, no pointers, that's about the only thing a segfault 
>>> could mean.
>>> Furthermore, null checking could be added to an implementation kind 
>>> of like bounds
>>> checking without changing the language spec.  I haven't made up my 
>>> mind fully yet,
>>> but I question whether adding lots of complexity to the language to 
>>> prevent a very
>>> easy to track down class of bugs, even if it's a common one, is 
>>> justified.
>>
>> I find this counterpoint to be a bit iffy.  The problem with null 
>> dereference problems isn't knowing that they're there: that's the easy 
>> part.  You helpfully get an exception to the face when that happens. 
>> The hard part is figuring out *where* the problem originally occurred. 
>> It's not when the exception is thrown that's the issue; it's the point 
>> at which you placed a null reference in a slot where you shouldn't have.
>>
>> Yes, we have invariants and contracts; but inevitably you're going to 
>> forget one, and it's that one slip-up that's going to bite you in the 
>> rear.
>>
>> One could use roughly the same argument for non-null references as for 
>> const: you could document it, but documentation is inevitably wrong or 
>> out of date.  :P
>>
>> That said, I wonder what's stopping us from implementing them today. 
>> Last time I checked (admittedly, that was like a year ago) we didn't 
>> have the compile-time magic necessary to completely and transparently 
>> proxy any given object.
>>
>> Ideally, we should be able to do this:
>>
>> class Foo
>> {
>>    void bar() { writefln("OH HAI WURLD!"); }
>> }
>>
>> NonNull!(Foo) foo = new Foo;
>> foo.bar();
>> Foo baz = foo;
>>
>> Off the top of my head, NonNull would require an opAssign, 
>> opImplicitCast to the templated type, and a way to build a full proxy 
>> of the underlying type.
>>
> 
> You took the idea slightly wrong. The default should be non-nullable,
> 
> Foo foo = null; // error
> Nullable!(Foo) foo2 = null; // ok
> 
> No implicit conversion is possible from Nullable!(Foo) to Foo (unless 
> one that throws an Exception on null-reference, but I believe it 
> contradicts the very idea of non-null references).
> 
>> It also just occured to me that this would probably break scope.  Damn.
>>
> 
> Scope is not broken. Quite the contrary, it goes on par with its meaning 
> - scope variable can't be null-initialized (it makes no sense at least).
> 
>> A nicer syntax would be appreciated, but probably isn't a 
>> requirement.  :)
>>
>>    -- Daniel
> 
> A nicer syntax is suggested (the one used by C#):
> 
> Foo nonNull = new Foo();
> Foo? possiblyNull = null;
Wouldn't this cause ambiguity with the "?:" operator?



More information about the Digitalmars-d mailing list