July 27, 2012
On Saturday, July 28, 2012 01:16:41 Namespace wrote:
> Therefore i hope that it will be official added into D. Otherwise of course i use it only for projects between me and my other students.
> 
> I don't know what is wrong with this shorthand. So why don't give it a try?

I don't even know what the last time I dereferenced a null pointer or null reference was. It almost never happens to me. I really think that if you're seeing very many null dererences, you're doing something fundamentally wrong with your code. At minimum, it indicates that you're not unit testing enough, since if you do that right, it'll catch the logic errors which give you null pointers/references very quickly.

> I'm absolutely sure that Walter will _never_ add real
> non-nullable references.
> All what will maybe come are further structs in std.alghorithm
> which blows up your code as assertions even do.

We will get a NotNull struct at some point (probably in std.typecons). It'll statically prevent assignments from null where it can and use assertions where it can't. Adding something to the language doesn't buy you much more than that anyway. At this point, any new language feature must meet a very high bar, and if we can do it in the library instead, we will. D is incredibly powerful and is already plenty complex, so we'll take advantage of that power where we can rather than trying to change the language further. D arguably has too many features as it is.

And as big a deal as you seem to think that this is, the _only_ C-based language that I'm aware of which has non-nullable references as part of the language is C#. So, while they may have their uses, it's actually very uncommon to have them, and since we can add a library type to do it, we can fix the problem without altering the language.

- Jonathan M Davis
July 27, 2012
Jonathan M Davis:

> Adding something to the language doesn't buy you much more than that anyway.

In the case of not-nullability, this isn't true. Integrating not-null in the type system allows the language to do things you can't do with NotNull, like:


// x is a nullable class reference
if (x == null) {
    ...
} else {
    // here the type system sees x as not null.
}

There are some other similar things you can't do with NotNull. In my enhancement request about not-nullability there are references to articles that explain the situation.


> D arguably has too many features as it is.

I don't agree, the number of features is not important. What's important is how clean and intelligently they are designed, how cleanly they interact with the other features. etc.


> And as big a deal as you seem to think that this is, the _only_ C-based language that I'm aware of which has non-nullable
> references as part of the language is C#.

This is not true. Scala, Rust, some new Java-derived languages, and more modern languages have not nullable references. In practice I think most or all new languages coming out now have this feature. In my opinion in few years programmers will expect to have it in all languages that are not too much old and that support some kind of nullable references.

Bye,
bearophile
July 28, 2012
On Saturday, July 28, 2012 01:48:00 bearophile wrote:
> Jonathan M Davis:
> > Adding something to the language doesn't buy you much more than that anyway.
> 
> In the case of not-nullability, this isn't true. Integrating not-null in the type system allows the language to do things you can't do with NotNull, like:
> 
> 
> // x is a nullable class reference
> if (x == null) {
>      ...
> } else {
>      // here the type system sees x as not null.
> }

??? What does it matter if the type system knows whether a pointer is null unless it's trying to warn you about dereferencing null? It's not checking for it. If we had null checks built in, that would buy you something, but we don't, and we're not going to, if nothing else because Walter is completely against it.

> There are some other similar things you can't do with NotNull. In my enhancement request about not-nullability there are references to articles that explain the situation.
> 
> > D arguably has too many features as it is.
> 
> I don't agree, the number of features is not important. What's important is how clean and intelligently they are designed, how cleanly they interact with the other features. etc.

There's always a cost to having more features. The more there are, the more that you have to know, and the more that it takes to learn the language. Having the features be well-designed definitely helps, and for the most part, I'm fine with the number of features that D has, but there probably are a few that ideally would be dropped but can't be at this stage (as was discussed not all that long ago in a big thread on what language features weren't useful), and adding more does come at a cost. A particular feature may be worth the cost that it brings, but the more features that you have, the more value each additional feature must bring to the table.

> > And as big a deal as you seem to think that this is, the _only_ C-based language that I'm aware of which has non-nullable references as part of the language is C#.
> 
> This is not true.

Actually, it is. I said "that I'm aware of." I didn't say that there weren't others, just that I didn't know of any others. But out of the mainstream C- based languages, it's definitely rare, much as it may be becoming less rare as new languages come along.

> Scala, Rust, some new Java-derived languages,
> and more modern languages have not nullable references. In
> practice I think most or all new languages coming out now have
> this feature. In my opinion in few years programmers will expect
> to have it in all languages that are not too much old and that
> support some kind of nullable references.

It's not necessarily a bad feature, but I do think that it's highly overrated, and regardless, there's no way that it's being added to D at this point in its life cycle. Maybe they'll be added in D3, but I wouldn't expect to see them before then at the earliest. The push right now is to use the language that we have to get things done rather than trying to constantly add features and tweak existing ones. There are probably some features that we wouldn't even have now if we had taken that approach earlier (e.g. base two literals).

- Jonathan M Davis
July 28, 2012
On Fri, 27 Jul 2012 22:16:05 +0200, Namespace <rswhite4@googlemail.com> wrote:

> And that is the explicit way with pre- and postconditions of Java, which i want to avoid.
>
> I see, the most of you prefer to write "try and catch" or use the java
> principle with explicit pre- and post conditions.
> The time will show, if D get therewith enough members to get serious.
> But this is what Java and C# have already.

This is a NotNull I just implemented. It is designed to create a strict
division between things that can be null, and those that cannot. The idea
being that the programmer should be aware of it when he needs to convert
between them, and whole call graphs can more easily be made free of
null checks.


-- 
Simen

July 28, 2012
Jonathan M Davis:

>> // x is a nullable class reference
>> if (x == null) {
>>      ...
>> } else {
>>      // here the type system sees x as not null.
>> }
>
> ??? What does it matter if the type system knows whether a pointer is null
> unless it's trying to warn you about dereferencing null?

In the else branch the state of the type of x is not-null, so as example in the else branch you are allowed to call a function that only accept not null references, with the x variable.
Not-nulls integrated in the type system makes sure you have well initialized variables in the class constructors in presence of inheritance and other complexities.
It also statically requires you to test for null before deferencing a nullable class reference, ans so on.
Those are the fruits that a good not-null implementation gives you. You can't do all this with the NotNull toy. NotNull solves only the easy part of the whole problem, and it's a small part.


> Actually, it is. I said "that I'm aware of."

Right :-)

Bye,
bearophile
July 28, 2012
> This is a NotNull I just implemented. It is designed to create a strict
> division between things that can be null, and those that cannot. The idea
> being that the programmer should be aware of it when he needs to convert
> between them, and whole call graphs can more easily be made free of
> null checks.

Foo f = new Foo();
some_function(NotNull!Foo(f)); <-explicit conversion and because it's a struct it's better to deliver it by ref.

// ---

Foo f = new Foo();
some_function(f);

// ...

void some_function(Foo f) in {
assert(f !is null);
} body {

^--- explicit. Unnecessary write effort.

A struct as solution to avoid not null references is a bad solution. It is a nice play tool but as solution it is crap. To pack my object into a struct with ensures that it is not null, what's the difference if i use only structs and avoid classes? Why should i initialize first my object and put it then into a struct if i can even use only structs?
That isn't comprehensible to me.
July 28, 2012
> Doing stuff like that makes your code completely unportable. It's _bad_
> practice. Don't go and try to redesign the language if you want to be playing
> nice with other people. If you can do something completely within the
> language, then that's different (other people may still hate what you're up to,
> but at least they can compile it), but don't use a preprocessor unless you
> really don't care about anyone else ever using your code but you, and even
> then, I'd argue against it, because if you get into the habit of doing that,
> you're screwed when you actually have to interact with other D programmers.
>
> - Jonathan M Davis

I can give them the "clone_*.d" files, which contains valid D code. No problem.
July 28, 2012
One more question: Where can I find an official statement by Walter _why_ he does not like such shorthands? Best viewed with understandable reasons.
Thanks in advance. :)
July 28, 2012
On Sat, 28 Jul 2012 10:20:56 +0200, Namespace <rswhite4@googlemail.com> wrote:

>> This is a NotNull I just implemented. It is designed to create a strict
>> division between things that can be null, and those that cannot. The
>> idea
>> being that the programmer should be aware of it when he needs to convert
>> between them, and whole call graphs can more easily be made free of
>> null checks.
>
> Foo f = new Foo();
> some_function(NotNull!Foo(f)); <-explicit conversion and because it's a
> struct it's better to deliver it by ref.

The conversion from a pointer to a struct containing a pointer should be without cost when compiling with optimizations on. The effect is exactly the same as with a pointer, which I hope you don't habitually pass by reference.


> A struct as solution to avoid not null references is a bad solution. It
> is a nice play tool but as solution it is crap. To pack my object into a
> struct with ensures that it is not null, what's the difference if i use
> only structs and avoid classes? Why should i initialize first my object
> and put it then into a struct if i can even use only structs?
> That isn't comprehensible to me.

Huh? I believe you have misunderstood something here. The struct is a form of smart pointer. It behaves like a pointer does, and lets you have polymorphism, inheritance and all that stuff that comes with classes. Granted, I have found a few issues with the version I posted (mostly to do with subclassing). Most have been fixed in this version, but some are unfixable until issue 1528 has been resolved.

-- 
Simen

July 28, 2012
Am Sat, 28 Jul 2012 05:07:44 +0200
schrieb "bearophile" <bearophileHUGS@lycos.com>:

> >> // x is a nullable class reference
> >> if (x == null) {
> >>      ...
> >> } else {
> >>      // here the type system sees x as not null.
> >> }
> >
> In the else branch the state of the type of x is not-null, so as
> example in the else branch you are allowed to call a function
> that only accept not null references, with the x variable.
> Not-nulls integrated in the type system makes sure you have well
> initialized variables in the class constructors in presence of
> inheritance and other complexities.
> It also statically requires you to test for null before
> deferencing a nullable class reference, ans so on.
> Those are the fruits that a good not-null implementation gives
> you. You can't do all this with the NotNull toy. NotNull solves
> only the easy part of the whole problem, and it's a small part.
> 
> Bye,
> bearophile

I found this an interesting read. The implementation likely doesn't interfere much with other language features (in a sense like @trusted does to templated functions that take potentially unsafe code as parameters).
I especially like how the compiler _statically_ knows, that x is not null in the else case. The runtime cost is moved from every call on x, to a single if-statement! It could require a little logic to parse complex conditions like "if (a == 1 && !x != null)", though ;)

-- 
Marco