May 19, 2013
On Sunday, 19 May 2013 at 21:36:17 UTC, Andrei Alexandrescu wrote:
> On 5/19/13 4:30 PM, Peter Alexander wrot
> OK, this is sensible. One question - would you be willing to type symbols as NullType!T instead of T to avoid these issues?
>
> Thanks,
>
> Andrei

Trying to come up with some once-and-for-all safe way to deal with null in languages which allow null references by default is something I wonder about now and then. This is due to my desire to adopt nice patterns for making my time spent working with a language safer and easier.

Option/Maybe I think only really works when the language has references as non-null by default. Otherwise, you're writing verbose code for Option/Maybe and lies the rest of the time. (I'm looking at Scala.) For D, I decided that my way to do it, to be applied almost all of the time, is to write contracts.

void func(Klass value) in {
    assert(value !is null);
} body {
}

This stops null from being passed through too many functions, so that alleviates a lot of problems. I think contract programming is a good solution for this, and it applies more generally to other kinds of invalid values. This can include values other than the default values.

May 19, 2013
On 5/19/13 5:11 PM, Walter Bright wrote:
> It reminded me of the hours I spent in high school determined to show
> that I could trisect an angle with a compass and a straightedge. There
> was always some tiny flaw :-)

Yah, sounds familiar. Did you prove the parallel postulate, too?

Andrei

May 19, 2013
On 5/19/13 5:56 PM, deadalnix wrote:
> On Sunday, 19 May 2013 at 21:02:57 UTC, Walter Bright wrote:
>> On 5/19/2013 11:22 AM, deadalnix wrote:
>>> The damn thing should have been initialized in the
>>> first place to avoid the bug.
>>
>> Sounds like you have the double-checked locking bug. Using a different
>> value to initialize it won't fix it.
>>
>
> No it sound like initalizing something to null, then initialize it
> properly, assume all over the place that it is initialized to something
> else, and in some rare code path it blows up.
>
> The fact that this occurs in a multithreaded environment made it super
> hard to debug, but the whole thing was properly synchronized.

How was there a bug if everything was properly synchronized? You either describe the matter with sufficient detail, or acknowledge the destruction of your anecdote. This is going nowhere.

Andrei


May 19, 2013
On 5/19/13 5:52 PM, deadalnix wrote:
> On Sunday, 19 May 2013 at 20:03:24 UTC, Andrei Alexandrescu wrote:
>> On 5/19/13 3:36 PM, deadalnix wrote:
>>> On Sunday, 19 May 2013 at 19:10:28 UTC, Andrei Alexandrescu wrote:
>>>> No, your argument is ridiculous. You make a yarn with precious little
>>>> detail that describes for everything everyone knows a textbook race
>>>> condition, essentially ask that you are taking by your word that
>>>> non-null would miraculously solve it, and, to add insult to injury,
>>>> and when we don't buy it, you put the burden of proof on us. This is
>>>> quite a trick, my hat is off to you.
>>>>
>>>
>>> I described a very usual null bug : something is set to null, then to a
>>> specific value. It is assumed not to be null. In a specific case it is
>>> null and everything explode.
>>>
>>> The concurrent context here made it especially hard to debug, but isn't
>>> the cause of the bug.
>>>
>>> Additionally, if you don't have enough information to understand what
>>> I'm saying, you are perfectly allowed to ask for additional details This
>>> isn't a shame.
>>
>> Your argument has been destroyed so no need to ask details about it.
>> Replace "null" with "invalid state" and it's the same race in any
>> system. Let's move on.
>>
>
> "I don't want t to understand because I know I'm right. The fact you
> solved that issue and I didn't is irrelevant, I know better."

Nobody knows what the issue is. It's all unstated assumptions leading to vague claims. You have been challenged to explain it so as to count as an anecdote in favor of non-null pointers - which it may as well be! -, and failed to raise to it.

Andrei
May 19, 2013
On Sunday, 19 May 2013 at 22:32:58 UTC, Andrei Alexandrescu wrote:
> How was there a bug if everything was properly synchronized? You either describe the matter with sufficient detail, or acknowledge the destruction of your anecdote. This is going nowhere.
>

I explained over and over. A field is initialized to null, while the object lock is owned, and later to its value, while it is locked. In the meantime, another thread access the object, owning the lock, assuming the field is always initialized.

The exact same problem arise quite often in the single threaded world : a reference is set to null, the dev try to be clever when initializing it, in a rare case it isn't, and everything blows up when it occurs.

It is simply easier to reproduce when things are single threaded, and are often quickly debugged in that case.

As explained, the multithreaded environment makes it super hard to debug, not the primary cause of the issue. The simply consistent in moving the initialization where it was set to null in the first place.

It is an instance of the very classic something may be null and code use it assuming it is never null.
May 19, 2013
On 5/19/2013 3:30 PM, Andrei Alexandrescu wrote:
> On 5/19/13 5:11 PM, Walter Bright wrote:
>> It reminded me of the hours I spent in high school determined to show
>> that I could trisect an angle with a compass and a straightedge. There
>> was always some tiny flaw :-)
>
> Yah, sounds familiar. Did you prove the parallel postulate, too?

No. That one was intuitively obvious!

May 19, 2013
On 5/19/2013 4:06 PM, deadalnix wrote:
> On Sunday, 19 May 2013 at 22:32:58 UTC, Andrei Alexandrescu wrote:
>> How was there a bug if everything was properly synchronized? You either
>> describe the matter with sufficient detail, or acknowledge the destruction of
>> your anecdote. This is going nowhere.
>>
>
> I explained over and over. A field is initialized to null, while the object lock
> is owned, and later to its value, while it is locked. In the meantime, another
> thread access the object, owning the lock, assuming the field is always
> initialized.

so, you have:
==========================
Thread A     Thread B

lock
   p = null
unlock
             lock
                *p = ...
             unlock
lock
   p = new ...
unlock
==========================
Although you are using locks, it still isn't properly synchronized. Changing the p=null to p=someothernonnullvalue will not fix it.
May 19, 2013
On 5/19/13 7:06 PM, deadalnix wrote:
> On Sunday, 19 May 2013 at 22:32:58 UTC, Andrei Alexandrescu wrote:
>> How was there a bug if everything was properly synchronized? You
>> either describe the matter with sufficient detail, or acknowledge the
>> destruction of your anecdote. This is going nowhere.
>>
>
> I explained over and over. A field is initialized to null, while the
> object lock is owned, and later to its value, while it is locked. In the
> meantime, another thread access the object, owning the lock, assuming
> the field is always initialized.

How does another thread thread accesses the object "owning the lock" when the assignment occurs under lock?

How would non-null fix this? Would the object have type Maybe?


Andrei
May 20, 2013
On Sunday, May 19, 2013 09:08:53 Andrei Alexandrescu wrote:
> Anyhow, this discussion should have finality. We could go on forever arguing the usefulness or lack thereof of non-nullable references. They didn't catch up in some languages and did in some. My personal opinion is "nice to have, but not greatly compelling".
> 
> It's reasonable to assume no major language changes will accommodate non-null references, so the next best thing would be to focus on a library solution. As Walter said, a library solution has the perk of allowing other interesting restricted types.

Wow, this thread really expanded since I looked at it last night. Yeah, I thought that it was clear that NonNullable or NotNull or whatever we want to call it was going to go in std.typecons and that that was going to be our solution to non-nullable references. This is one of those discussions that I should probably just stay out of, since it never seems to go anywhere useful. We've already decided on a solution. We just haven't gotten it into the standard library yet.

- Jonathan M Davis
May 20, 2013
On 5/19/2013 3:04 PM, deadalnix wrote:
> Same argument Walter like to make about very rare failure cases apply here.


1. rare as in programmers rarely create such a bug

2. rare as in being rare for an existing bug to show itself

I was referring to (1), while you are referring to (2).