February 09, 2009
Andrei Alexandrescu:
> Non-nullable types are proper subtypes of nullable types. There is no added safety in requiring a cast.

Yes, sorry, often I misunderstood (I was thinking of the opposite situation).

Bye,
bearophile
February 09, 2009
On Mon, 09 Feb 2009 04:19:55 +0000, Brian wrote:

> On Mon, 09 Feb 2009 04:25:55 +0300, Denis Koroskin wrote:
> 
>> So, let's ask the community: Would you like to see nullable types in D?
>> 
>> http://www.micropoll.com/akira/mpview/539369-138652 (please, don't
>> abuse by voting multiple time)
>> 
>> Explain your reasoning in newsgroups. Thank you.
> 
> i vote yes, i would absolutely love non-nullable types. in some cases i even use dummy objects to avoid null checks.

well, at the very least id like to see a (optional) warning/error for uninitialized pointers. This way I can be certain there are absolutely zero null pointers unless the null keyword itself is used. A quick search for 'null' would be guaranteed to show all possibly null variables. I know I'm not the first to wish for such. (Does a warning exist yet that I don't know about?)
February 09, 2009
Christopher Wright wrote:
> Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly.

That misses the point completely. It's not about you (as the programmer) getting NPEs; it's about the user getting bug-free software in the first place.

In most cases a segfault/NPE is easy to track down for the programmer, I guess nobody would object to this. But once the software is shipped, it's a very serious problem: It's a situation the programmer didn't thought about so you usually have a data loss.

I really like the approach of the Nice[1] language: Before you can access a nullable type you have to test whether it's null. After the test, the type is automagically converted to a nonnullable type. This language doesn't have a NPE, so you *know* that your software is bug-free in this regard.

[1] http://nice.sf.net

Sebastian
February 09, 2009
On Mon, 09 Feb 2009 18:20:56 +0000, Brian wrote:
> well, at the very least id like to see a (optional) warning/error for uninitialized pointers. This way I can be certain there are absolutely zero null pointers unless the null keyword itself is used. A quick search for 'null' would be guaranteed to show all possibly null variables. I know I'm not the first to wish for such. (Does a warning exist yet that I don't know about?)

just to clarify, this is what id like. given this code:

void main() {
    Foo f;
    bar(null);
}
class Foo() {}
void bar(Foo) {}

$ dmd main.d
Completed Successfully

$ dmd -wnull main.d
main.d(2): warning: variable 'f' is default initialized to null
main.d(3): warning: passing null as argument to function expecting Foo

To prevent the warnings, you would need to change main to this:
void main() {
    Foo f = null;
    bar(cast(Foo)null);
}
February 10, 2009
"Sebastian Biallas" <groups.5.sepp@spamgourmet.com> wrote in message news:gmpsun$14dj$1@digitalmars.com...
> Christopher Wright wrote:
>> Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly.
>
> That misses the point completely. It's not about you (as the programmer) getting NPEs; it's about the user getting bug-free software in the first place.
>
> In most cases a segfault/NPE is easy to track down for the programmer, I guess nobody would object to this. But once the software is shipped, it's a very serious problem: It's a situation the programmer didn't thought about so you usually have a data loss.
>
> I really like the approach of the Nice[1] language: Before you can access a nullable type you have to test whether it's null. After the test, the type is automagically converted to a nonnullable type. This language doesn't have a NPE, so you *know* that your software is bug-free in this regard.
>
> [1] http://nice.sf.net
>
> Sebastian

Interesting, that is very nice, I like that idea a lot.


February 11, 2009
Sebastian Biallas wrote:
> Christopher Wright wrote:
>> Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly.
> 
> That misses the point completely. It's not about you (as the programmer) getting NPEs; it's about the user getting bug-free software in the first place.
> 
> In most cases a segfault/NPE is easy to track down for the programmer, I guess nobody would object to this. But once the software is shipped, it's a very serious problem: It's a situation the programmer didn't thought about so you usually have a data loss.

Your language features should get rid of bugs that are easy to make and difficult to track down. It's not worthwhile to alter your language to remove easily found, easily fixed bugs.

Logic errors are difficult to find. Your language cannot help you eliminate those (though contracts and unittests can help you find them). If you do not test your software extensively, you will ship software with logic errors. The testing required to find logic errors will also find low-level errors like segfaults.
February 11, 2009
On Wed, Feb 11, 2009 at 3:40 PM, Christopher Wright <dhasenan@gmail.com> wrote:
>
> Your language features should get rid of bugs that are easy to make and difficult to track down. It's not worthwhile to alter your language to remove easily found, easily fixed bugs.

Except when someone passes a null reference into a large, complex data structure and that reference is passed around blindly and never dereferenced until somewhere far down the line, giving you a segfault in a program location that you never would have expected.  By then it's much more difficult to figure out where that null reference came from.  I've had a much larger share of these kinds of null reference errors than the "oops someone passed a null into my function and I didn't account for it" kind.  Disallowing null references on most public interface functions from the beginning would make those kinds of bugs nonexistent.

Otherwise, you have to put explicit runtime null checks on every public interface function, and woe to the guy who forgets to do that. Not to mention you now have to write all these stupid unittests to throw nulls at the code to see if it barfs correctly, rather than it being a simple error caught by the compiler.  This reeks of the development problems that dynamic languages have!  We have static compilation for a reason; why not take advantage of it?

Having null references be the default - nay, the only - option is a useless bit of C arcana that should be dropped.  It's a dangerous use of in-band signaling on par with error return codes.
February 11, 2009
Jarrett Billingsley wrote:
> On Wed, Feb 11, 2009 at 3:40 PM, Christopher Wright <dhasenan@gmail.com> wrote:
>> Your language features should get rid of bugs that are easy to make and
>> difficult to track down. It's not worthwhile to alter your language to
>> remove easily found, easily fixed bugs.
> 
> Except when someone passes a null reference into a large, complex data
> structure and that reference is passed around blindly and never
> dereferenced until somewhere far down the line, giving you a segfault
> in a program location that you never would have expected.  By then
> it's much more difficult to figure out where that null reference came
> from.  I've had a much larger share of these kinds of null reference
> errors than the "oops someone passed a null into my function and I
> didn't account for it" kind.  Disallowing null references on most
> public interface functions from the beginning would make those kinds
> of bugs nonexistent.
> 
> Otherwise, you have to put explicit runtime null checks on every
> public interface function, and woe to the guy who forgets to do that.

Or add an invariant. You know which field is null when it shouldn't be, so that should be simple enough. Or use a property rather than a field and add a contract.

This covers the same cases that non-nullable types do, though admittedly with slightly less granularity.

A complex datastructure might have a complex initialization process that is best spread across a few lines of code rather than happening all at once. If that is the case, you *can't* use non-nullable types, because that restriction isn't valid until the object is fully initialized. But you can still use contracts here.
February 11, 2009
On Wed, Feb 11, 2009 at 5:23 PM, Christopher Wright <dhasenan@gmail.com> wrote:
> Or add an invariant. You know which field is null when it shouldn't be, so that should be simple enough. Or use a property rather than a field and add a contract.
>
> This covers the same cases that non-nullable types do, though admittedly with slightly less granularity.
>
> A complex datastructure might have a complex initialization process that is best spread across a few lines of code rather than happening all at once. If that is the case, you *can't* use non-nullable types, because that restriction isn't valid until the object is fully initialized. But you can still use contracts here.

What is your response to the part of my post that was cut off?  You know, the part about having to write stupid contracts and how the compiler can and should be checking this kind of thing?
February 11, 2009
Christopher Wright wrote:
> Sebastian Biallas wrote:
>> Christopher Wright wrote:
>>> Oh, and I vote no. I think it's needless complexity. I code without any special care for null objects, and I get a segfault or NullReferenceException maybe once a week, probably less. I've always been able to track down the bug very quickly.
>>
>> That misses the point completely. It's not about you (as the programmer) getting NPEs; it's about the user getting bug-free software in the first place.
>>
>> In most cases a segfault/NPE is easy to track down for the programmer, I guess nobody would object to this. But once the software is shipped, it's a very serious problem: It's a situation the programmer didn't thought about so you usually have a data loss.
> 
> Your language features should get rid of bugs that are easy to make and difficult to track down. It's not worthwhile to alter your language to remove easily found, easily fixed bugs.

Once your software is running, an easy to fix bug is just as bad as an hard to fix bug. It's a bug after all.

Of course, you can ask the question whether it's worthwhile to alter the language. Well, for D this is still possible, while other languages will have NPEs till the end of the world.

> Logic errors are difficult to find. Your language cannot help you eliminate those (though contracts and unittests can help you find them). 

"We shouldn't try to avoid bugs of type A because we can't avoid bugs of type B" is a logical fallacy.

> If you do not test your software extensively, you will ship software with logic errors. The testing required to find logic errors will also find low-level errors like segfaults.

Uh.... sorry, but reality proves you wrong. I (and the rest of the world) get NPE in various kinds of extensively tested software.

And we can get rid of *all* these errors by a simple language change (A change that should have been done centuries ago). This is a case where you can automatically proof correctness of a specific detail of your software. A chance that shouldn't be ignored because, uh, it's an easy to fix bug (If your rocket to the moon explodes because of an easy to fix bug, well, I don't think that is helps you that it was at least an easy to fix bug).

Sebsatian