References in D

Chad J chadjoan at __spam.is.bad__gmail.com
Fri Oct 5 22:06:19 PDT 2012


On 10/03/2012 01:31 PM, "Franciszek Czekała" <home at valentimex.com>" wrote:
> On Wednesday, 3 October 2012 at 16:33:15 UTC, Simen Kjaeraas wrote:
>> On 2012-10-03, 18:12, wrote:
>>
>
>> They make sure you never pass null to a function that doesn't expect
>> null - I'd say that's a nice advantage.
>
> No, it is meaningless. If you have a class which is supposed to hold a
> prime number and you pass it to a function are you going to check each
> time that the value is indeed prime? That would kill the efficiency of
> your program guaranteed. So you would be happy to know that the
> reference is non-null but you would take it for granted the value is
> indeed prime? Does it make any sense?
> I maintain that this non-null "advantage" does not warrant to make the
> language more complicated even by a tiny bit. It is dwarfed by normal
> considerations related to program correctness.
>

It would be cool to have templates like this:

51.  bool isPrime(int val)
52.  {
53.  	...
54.  }

101. Watch!(int,&isPrime) primeNumber = primeGenerator();
102. primeNumber = 8;
103. doStuff();
104. checkPrime(primeNumber); /+ Crash! +/
Error: checkPrime(primeNumber): primeNumber is not prime.
primeNumber: isPrime returned false after assignment at
   (foobar.d, line 102)

~or~

101. Constrain!(int,&isPrime) primeNumber = primeGenerator();
102. primeNumber = 8; /+ Crash! +/
103. doStuff();
104. checkPrime(primeNumber);
foobar.d, line 102: isPrime returned false after assignment.

For convenience one could define this:
alias Constrain!(int,&isPrime) PrimeInt;

I think this would be sufficient for the cases that are considerable 
less common than errant null references.  I do think these capabilities 
should exist.  Assumptions suck: allowing invalid data to propogate in 
non-local ways is BAD.

> With default null references:
> A)either null is an expected non-value for the type (like in the chess
> example), checking for it is part of normal processing then
> B) or null is not a valid value, then there is no need to check for it.
> If you get a null reference it is a bug. It is like getting a 15 for
> your prime number. You do not put checks like that in your code. You
> test your prime generation routine not the consumers. If your function
> gets a null reference when it should not, some other part of your
> program is buggy. You do not process bugs in your code - you remove them
> from it.
>

Please explain how a program printing
Segmentation fault
tells me where the null came from?

If I'm lucky, I even get a stack trace, which is still not good enough 
in the cases that are actually non-trivial to solve.

My problem with using nullable values /everywhere/ is that they make it 
very difficult to determine exactly what code is /producing/ the null. 
If there's no stack trace information then it isn't even possible to 
know where the consumer is in a lot of cases.

> However with D, dereferencing an uninitialized reference is well defined
> - null is not random data: you get a well-defined exception and you know
> you are dealing with unitialized data. This is easy to fix. You just go
> up the stack and check where the reference comes from. Much easier
> probably than finding out why your prime numbers turn out to be
> divisible by 3. How about introducing some syntax that will rule this out?
>

You... you... you /JUST/ go up the stack.  Nope.

I've been betrayed by this approach many times in the past.  Can you 
tell? ;)

Copy-pasta from my previous post:

void main()
{
     void* x = a(b());
     c();
     while(goobledegook)
     {
         x = p();
         d(x);
     }
     e(x); /+ Crash! x is null. +/
}

Where did x's null value come from?  Not a. Not p; the while loop 
happened to be never executed.  To say "b" would be closer, but still 
imprecise.  Actually it was created in the q() function that was called 
by u() that was called by b() which then created a class that held the 
null value and was passed to a() that then dereferenced the class and 
returned the value stored in the class that happened to be null.  nulls 
create very non-local bugs, and that's why they frustrate me to no end 
sometimes.

(end of copy-pasta)

> To quote (loosely) Mr. Walter Bright from another discussion: how many
> current bugs in dmd are related to default null references?

I don't know, but when I was trying to debug a certain dmd bug that was 
blocking my progress.  It took a day of figuring out what was creating 
the damn null values.  That could have been much faster.  The bug was 
not caused by null values, but they severely complicated debugging.  So 
no, I don't want to do that work.  I want the compiler to do it for me. 
  (I gave up on fixing that bug because it required rewriting 
non-trivial portions of dmd.)

----------------------

If you have not experienced these frustrations, then you are very 
fortunate.  Please spread your fortune and be more understanding of the 
problems faced by others.


More information about the Digitalmars-d mailing list