May 19, 2013
On Saturday, 18 May 2013 at 20:59:41 UTC, Simen Kjaeraas wrote:
> @disable this is awesome, really. And you're right that it's even better than
> simple non-nullable pointers. Lastly, it's great that it's getting fixes. It's
> been one of my favorite non-working features. :p
>

The subject here is default constructor, not really nullable pointer. @disable this() cost as much as default constructor, but provide less. I don't see any objective reason to limit default constructor as disabled but not enabled.

I'd even argue that it actually cost more as it introduce yet another special case.

> In a way, I fear that we'll end up like C++, with bare pointers/references
> being considered experts-only and 'special use', and everyone will use smart
> pointers instead.

No what will happen it that we will have null all over the place with missing check, and no stack trace when it fails, because NullPointerError have been decided to be bad.

regular references/pointer are used way more than in C++ because you don't need to do the manual memory management that goes with it in D.

We will have more bugs and slower programs due to null checks all over the place, and unexpressed assumption about what can be null and what cannot.
May 19, 2013
On 5/18/2013 5:04 PM, deadalnix wrote:
> On Saturday, 18 May 2013 at 20:59:41 UTC, Simen Kjaeraas wrote:
>> @disable this is awesome, really. And you're right that it's even better than
>> simple non-nullable pointers. Lastly, it's great that it's getting fixes. It's
>> been one of my favorite non-working features. :p
>>
>
> The subject here is default constructor, not really nullable pointer. @disable
> this() cost as much as default constructor, but provide less. I don't see any
> objective reason to limit default constructor as disabled but not enabled.
>
> I'd even argue that it actually cost more as it introduce yet another special case.

    this() { assert(0); }

makes for a runtime check, not a compile time one. Compile time checks are more efficient in both programmer time and run time.

Note that C++11 8.4.3 has @disable as well, in the form:

   S() = delete;

>> In a way, I fear that we'll end up like C++, with bare pointers/references
>> being considered experts-only and 'special use', and everyone will use smart
>> pointers instead.
>
> No what will happen it that we will have null all over the place with missing
> check, and no stack trace when it fails, because NullPointerError have been
> decided to be bad.
>
> regular references/pointer are used way more than in C++ because you don't need
> to do the manual memory management that goes with it in D.
>
> We will have more bugs and slower programs due to null checks all over the
> place, and unexpressed assumption about what can be null and what cannot.

With NotNull, the runtime check only happens upon assignment and initialization from a pointer type. Dereferencing, copying, etc., of NotNull entails zero runtime overhead and no checks.
May 19, 2013
On Sunday, 19 May 2013 at 00:14:26 UTC, Walter Bright wrote:
>
>     this() { assert(0); }
>
> makes for a runtime check, not a compile time one. Compile time checks are more efficient in both programmer time and run time.
>
> Note that C++11 8.4.3 has @disable as well, in the form:
>
>    S() = delete;
>

D has @disable. If default constructor are allowed, default constructor can be disabled, as any other declared symbol.

> With NotNull, the runtime check only happens upon assignment and initialization from a pointer type. Dereferencing, copying, etc., of NotNull entails zero runtime overhead and no checks.

People go for the shortest path. You end up having nullable everywhere. Experience have been a countless amount of time in bazillion programming languages. But it is probably too late to fix this in D anyway.
May 19, 2013
On Sunday, May 19, 2013 02:22:43 Simen Kjaeraas wrote:
> Or... possibly, the current holes in @disable are fixed, and NonNull!T becomes the default, because we tell people to always use them, rather than flail our arms and behave like idiots. ("regular pointers are broken, use NonNull!T" is a pretty good argument if it's true)

I've never understood why so many people feel that nullable pointers are a problem. Clearly, many people do, but personally, I've rarely had problems with them, and there are plenty of cases where not being to make a pointer null would really suck (which is why we're forced to have std.typecons.Nullable for non-reference types). I'm not arguing against having non-nullable pointers, but I'd probably almost never use them myself, as I really don't think that they'd be buying me much. In my experince, problems with null pointers are extremely rare and easily caught.

-  Jonathan M Davis
May 19, 2013
On 5/18/2013 5:23 PM, deadalnix wrote:
> On Sunday, 19 May 2013 at 00:14:26 UTC, Walter Bright wrote:
>>
>>     this() { assert(0); }
>>
>> makes for a runtime check, not a compile time one. Compile time checks are
>> more efficient in both programmer time and run time.
>>
>> Note that C++11 8.4.3 has @disable as well, in the form:
>>
>>    S() = delete;
>>
>
> D has @disable. If default constructor are allowed, default constructor can be
> disabled, as any other declared symbol.

I understand that. But the rationale you gave for having a default constructor was to be able to disable default construction.


>> With NotNull, the runtime check only happens upon assignment and
>> initialization from a pointer type. Dereferencing, copying, etc., of NotNull
>> entails zero runtime overhead and no checks.
>
> People go for the shortest path. You end up having nullable everywhere.
> Experience have been a countless amount of time in bazillion programming
> languages. But it is probably too late to fix this in D anyway.

I know that some languages have a special syntax for non-null pointers. I disliked this solution for D because non-nullable pointers are just one instance of creating a type with a limited set of values. Why not go for a general solution? Why not create a mechanism where a type can be defined that can only consist of prime numbers, for example? Why not ranged integer types?
May 19, 2013
On 05/19/2013 03:20 AM, Walter Bright wrote:
> On 5/18/2013 5:23 PM, deadalnix wrote:
>> ...
>> People go for the shortest path. You end up having nullable everywhere.
>> Experience have been a countless amount of time in bazillion programming
>> languages. But it is probably too late to fix this in D anyway.
>
> I know that some languages have a special syntax for non-null pointers.

The saner ones have special syntax for _nullable_ types.

> I disliked this solution for D because non-nullable pointers are just
> one instance of creating a type with a limited set of values.

I think this is the wrong direction of approaching the problem.

D-style nullable references are an example of adding a value to a type whose typing judgements are invalid for that value:

class C{ void foo(){ ... }

void main(){
    typeof(null) a;
    a.foo(); // compile-time error
    C c = a;
    c.foo(); // segmentation fault
}

null is not a C, as it does not provide a C.foo method.

> Why not go for a general solution?

You may want a type that has more than one special value. Why have language support for exactly one special value? In any case, why have unsound type checking for the sake of special values?

> Why not create a mechanism where a type can be defined that can only consist of prime numbers, for example?

There are programming languages that allow this.

> Why not ranged integer types?

May 19, 2013
On 05/19/2013 02:32 AM, Jonathan M Davis wrote:
> On Sunday, May 19, 2013 02:22:43 Simen Kjaeraas wrote:
>> Or... possibly, the current holes in @disable are fixed, and NonNull!T
>> becomes the default, because we tell people to always use them, rather
>> than flail our arms and behave like idiots. ("regular pointers are
>> broken, use NonNull!T" is a pretty good argument if it's true)
>
> I've never understood why so many people feel that nullable pointers are a
> problem. Clearly, many people do, but personally, I've rarely had problems
> with them, and there are plenty of cases where not being to make a pointer
> null would really suck (which is why we're forced to have
> std.typecons.Nullable for non-reference types). I'm not arguing against having
> non-nullable pointers, but I'd probably almost never use them myself, as I
> really don't think that they'd be buying me much. In my experince, problems
> with null pointers are extremely rare and easily caught.
>
> -  Jonathan M Davis
>

I don't write a lot of buggy code for myself either. You are arguing for leaving out cheap code documentation. Also, in a sane system you'd be forced to use types without a null value in many cases, as potentially null references ought not be dereferenced. i.e. potentially null would mean they _really_ can be null, because otherwise an actual reference to a value type could be used.
May 19, 2013
On 5/18/2013 1:39 PM, Walter Bright wrote:
> Already reported:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=10115

And Kenji has already posted a fix!

What can I say, other than Awesome!
May 19, 2013
On Sunday, 19 May 2013 at 01:20:31 UTC, Walter Bright wrote:
> I understand that. But the rationale you gave for having a default constructor was to be able to disable default construction.
>

RAII or construction based on template parameters.

> I know that some languages have a special syntax for non-null pointers. I disliked this solution for D because non-nullable pointers are just one instance of creating a type with a limited set of values. Why not go for a general solution? Why not create a mechanism where a type can be defined that can only consist of prime numbers, for example? Why not ranged integer types?

Actually most languages does the reverse. They have non nullable type, and provide Nullable/Option/Maybe/whatever to allow for nullable type. It allow to ensure that null don't pops up in unexpected places, and that null must be handled when it is an option.

The current solution is to rely on faith, and I remember someone talking about that at DConf recently.

Now that what other languages does is cleared, let's do some consideration on null.

A pointer point on something. For instance, an int* point on an integer. null doesn't point on a integer. Non nullable pointer aren't a restricted set of values, as, by definition, null isn't a value that point to an int. That doesn't stand either.

D already have thing like Nullable in the standard lib. Introducing Maybe is also pretty easy. Adding NonNullable in addition to Nullable sound like something is not quite right.

The benefit we get from null, ie having a default initialization for everything, is moot if @disable this() is introduced, so it is questionable at this point how useful it really is except as make up over current implementation deficiencies.

Finally it has to be added that null cause holes in @safe in ways that are difficult to impossible to solve.
May 19, 2013
On Sunday, May 19, 2013 05:54:46 deadalnix wrote:
> Actually most languages does the reverse. They have non nullable type, and provide Nullable/Option/Maybe/whatever to allow for nullable type. It allow to ensure that null don't pops up in unexpected places, and that null must be handled when it is an option.

Most languages? I'm not aware of even _one_ C-based language that doesn't have null as the default for pointer/references types. They may have non-nullable reference types in addition to the nullable ones (though that's still rare in my experience), but they were all added later. The closest that there is is C++'s references, which aren't rebindable and in many ways act more like aliases than pointers.

Functional languages do less with nullable, but given D's ancestory, it's not at all surprising that nullable is the default, and it would be very bizarre if it weren't.

- Jonathan M Davis