Non-nullable references, again

Denis Koroskin 2korden at gmail.com
Wed Dec 31 05:01:52 PST 2008


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;



More information about the Digitalmars-d mailing list