February 10, 2009
Andrei Alexandrescu wrote:
> Daniel Keep wrote:
>>
>> Denis Koroskin wrote:
>>> Andrei Alexandrescu Wrote:
>>>
>>>> Denis Koroskin wrote:
>>>>> On Mon, 09 Feb 2009 13:48:39 +0300, Alex Burton <alexibu@mac.com> wrote:
>>>>>
>>>>>> I think it makes no sense to have nullable pointers in a high level language like D.
>>>>>>
>>>>>> In D :
>>>>>>
>>>>>> X x = new X;
>>>>>> This is a bit redundant, if we take away the ability to write X x; to mean X x = 0; then we can have X x; mean X x = new X;
>>>>>> If the class has a ctor then we can write X x(32); instead of X x = new X(32);
>>>>>> Only when the types of the pointer and class are different do we need to write X x = new Y;
>>>>>> We can do this syntactically in D because classes cannot be instantiated on the stack (unless scope is used, which I have found a bit pointless, as members are not scope so no deterministic dtor)
>>>>>>
>>>>>> This makes the code much less verbose and allows code to change from X being a struct to X being a class without having to go around and change all the X x; to X = new X;
>>>>>>
>>>>>> As I said in the nullable types thread:
>>>>>> Passing 0 or 0x012345A or anything else that is not a pointer to an instance of X to a variable declared as X x is the same as mixing in a bicycle when a recipe asks for a cup of olive oil.
>>>>>>
>>>>>> There are much better, and less error prone ways to write code in a high level language than allowing null pointers.
>>>>>>
>>>>>> Alex
>>>>> I remember Andrei has showed interest in unification of the way value and reference types are instantiated:
>>>>>
>>>>> Foo foo(arg1, arg2); // valid instance, be it reference of value type
>>>>> Bar bar; // same here (default ctor is called)
>>>>>
>>>>> and ditch 'new' keyword altogether.
>>>> That would be nice but Walter says he dislikes a dynamic allocation going under the covers.
>>>>
>>> How about dynamic closures? It's way much harder to /properly/ determine whether a closure allocates that to determine if Foo foo; allocates But it reduces syntax complexity (by removing one syntax construct) and make structs and classes a little bit more intechangeble, which is a plus, I think.
>>>
>>>>> Note that you can't delete non-nullable reference so 'delete' keyword is not needed, too (use scope instead). Nullable types, however, may be recycled with e.g. GC.delete(foo);
>>>> Delete-ing either non- or yes-nullable references is just as dangerous. IMHO the delete facility of the GC should be eliminated. (Long story.)
>>>>
>>> I competely agree. Don't remember last time I used delete in D.
>>>
>>>> Andrei
>>
>> I've used it for managing very large chunks of memory that I don't want
>> hanging around.  Access to this memory is generally mediated by small
>> proxy object using reference counting so I know when it's OK to nuke
>> that big chunk.
>>
>> GC is wonderful, but there are times where you just can't trust it.
>>
>>   -- Daniel
> 
> Sure. My suggested framework is one in which you'd use malloc for those allocations. Then you can free. But plopping delete in the midst of a GC system... that's just uncalled for.
> 
> Andrei

Using malloc would probably force us to overwrite a class' new operator. Then you no longer had the choice between automatic and manual freeing, because the new operator implementation is fixed. Basically, using malloc would add a load of crap to the program. Having delete (or a function like GC.delete()) is a so much simpler and nicer solution. Why would you remove that?
February 10, 2009
Nick Sabalausky wrote:
> "Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gmpd71$8uj$1@digitalmars.com...
>> Alex Burton wrote:
>>> I think it makes no sense to have nullable pointers in a high level language like D.
>> Oh, and how do you intend to make linked lists?  Or trees?  Or any
>> non-trivial data structure?
>>
> 
> Null Object Pattern:
> --------------
> class LinkedListNode(T)
> {
>     LinkedListNode!(T) next;
> 
>     private static LinkedListNode!(T) _end;
>     static LinkedListNode!(T) end() {
>         return _end;
>     }
>     static this() {
>          _end = new LinkedListNode!(T);
>     }
> }
> --------------


What is "next" for the _end node?

Andrei
February 10, 2009
On Tue, 10 Feb 2009 17:11:06 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Nick Sabalausky wrote:
>> "Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gmpd71$8uj$1@digitalmars.com...
>>> Alex Burton wrote:
>>>> I think it makes no sense to have nullable pointers in a high level language like D.
>>> Oh, and how do you intend to make linked lists?  Or trees?  Or any
>>> non-trivial data structure?
>>>
>>  Null Object Pattern:
>> --------------
>> class LinkedListNode(T)
>> {
>>     LinkedListNode!(T) next;
>>      private static LinkedListNode!(T) _end;
>>     static LinkedListNode!(T) end() {
>>         return _end;
>>     }
>>     static this() {
>>          _end = new LinkedListNode!(T);
>>     }
>> }
>> --------------
>
>
> What is "next" for the _end node?
>
> Andrei

Perhaps, 'this' (i.e. itself).
February 10, 2009
Denis Koroskin wrote:
> On Tue, 10 Feb 2009 17:11:06 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> Nick Sabalausky wrote:
>>> "Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gmpd71$8uj$1@digitalmars.com...
>>>> Alex Burton wrote:
>>>>> I think it makes no sense to have nullable pointers in a high level language like D.
>>>> Oh, and how do you intend to make linked lists?  Or trees?  Or any
>>>> non-trivial data structure?
>>>>
>>>  Null Object Pattern:
>>> --------------
>>> class LinkedListNode(T)
>>> {
>>>     LinkedListNode!(T) next;
>>>      private static LinkedListNode!(T) _end;
>>>     static LinkedListNode!(T) end() {
>>>         return _end;
>>>     }
>>>     static this() {
>>>          _end = new LinkedListNode!(T);
>>>     }
>>> }
>>> --------------
>>
>>
>> What is "next" for the _end node?
>>
>> Andrei
> 
> Perhaps, 'this' (i.e. itself).

Then there's going to be quite a few infinite loops out there...

Andrei
February 10, 2009
On Tue, 10 Feb 2009 17:40:36 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Denis Koroskin wrote:
>> On Tue, 10 Feb 2009 17:11:06 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> Nick Sabalausky wrote:
>>>> "Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gmpd71$8uj$1@digitalmars.com...
>>>>> Alex Burton wrote:
>>>>>> I think it makes no sense to have nullable pointers in a high level language like D.
>>>>> Oh, and how do you intend to make linked lists?  Or trees?  Or any
>>>>> non-trivial data structure?
>>>>>
>>>>  Null Object Pattern:
>>>> --------------
>>>> class LinkedListNode(T)
>>>> {
>>>>     LinkedListNode!(T) next;
>>>>      private static LinkedListNode!(T) _end;
>>>>     static LinkedListNode!(T) end() {
>>>>         return _end;
>>>>     }
>>>>     static this() {
>>>>          _end = new LinkedListNode!(T);
>>>>     }
>>>> }
>>>> --------------
>>>
>>>
>>> What is "next" for the _end node?
>>>
>>> Andrei
>>  Perhaps, 'this' (i.e. itself).
>
> Then there's going to be quite a few infinite loops out there...
>
> Andrei

No, you just need to have a private ctor:

class LinkedListNode(T)
{
    private enum Foo {
       Bar,
    }

    private this(Foo foo) // not accessible outside of the module
    {
        _next = this;
    }

    static this()
    {
        _end = new LinkedListNode!(T)(Foo.Bar);
    }

    private LinkedListNode _next;
}
February 10, 2009
Denis Koroskin wrote:
> On Tue, 10 Feb 2009 17:40:36 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> Denis Koroskin wrote:
>>> On Tue, 10 Feb 2009 17:11:06 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>>
>>>> Nick Sabalausky wrote:
>>>>> "Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gmpd71$8uj$1@digitalmars.com...
>>>>>> Alex Burton wrote:
>>>>>>> I think it makes no sense to have nullable pointers in a high level language like D.
>>>>>> Oh, and how do you intend to make linked lists?  Or trees?  Or any
>>>>>> non-trivial data structure?
>>>>>>
>>>>>  Null Object Pattern:
>>>>> --------------
>>>>> class LinkedListNode(T)
>>>>> {
>>>>>     LinkedListNode!(T) next;
>>>>>      private static LinkedListNode!(T) _end;
>>>>>     static LinkedListNode!(T) end() {
>>>>>         return _end;
>>>>>     }
>>>>>     static this() {
>>>>>          _end = new LinkedListNode!(T);
>>>>>     }
>>>>> }
>>>>> --------------
>>>>
>>>>
>>>> What is "next" for the _end node?
>>>>
>>>> Andrei
>>>  Perhaps, 'this' (i.e. itself).
>>
>> Then there's going to be quite a few infinite loops out there...
>>
>> Andrei
> 
> No, you just need to have a private ctor:

I meant that code that fails to check for _end when iterating through a list will never stop.

Andrei
February 10, 2009
On Tue, 10 Feb 2009 19:41:25 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Denis Koroskin wrote:
>> On Tue, 10 Feb 2009 17:40:36 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>
>>> Denis Koroskin wrote:
>>>> On Tue, 10 Feb 2009 17:11:06 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>>>
>>>>> Nick Sabalausky wrote:
>>>>>> "Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gmpd71$8uj$1@digitalmars.com...
>>>>>>> Alex Burton wrote:
>>>>>>>> I think it makes no sense to have nullable pointers in a high level language like D.
>>>>>>> Oh, and how do you intend to make linked lists?  Or trees?  Or any
>>>>>>> non-trivial data structure?
>>>>>>>
>>>>>>  Null Object Pattern:
>>>>>> --------------
>>>>>> class LinkedListNode(T)
>>>>>> {
>>>>>>     LinkedListNode!(T) next;
>>>>>>      private static LinkedListNode!(T) _end;
>>>>>>     static LinkedListNode!(T) end() {
>>>>>>         return _end;
>>>>>>     }
>>>>>>     static this() {
>>>>>>          _end = new LinkedListNode!(T);
>>>>>>     }
>>>>>> }
>>>>>> --------------
>>>>>
>>>>>
>>>>> What is "next" for the _end node?
>>>>>
>>>>> Andrei
>>>>  Perhaps, 'this' (i.e. itself).
>>>
>>> Then there's going to be quite a few infinite loops out there...
>>>
>>> Andrei
>>  No, you just need to have a private ctor:
>
> I meant that code that fails to check for _end when iterating through a list will never stop.
>
> Andrei

No, error like that will be detected at compile time (comparison against null is disallowed for non-nullable reference).
February 10, 2009
Denis Koroskin wrote:
> On Tue, 10 Feb 2009 19:41:25 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> 
>> Denis Koroskin wrote:
>>> On Tue, 10 Feb 2009 17:40:36 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>>
>>>> Denis Koroskin wrote:
>>>>> On Tue, 10 Feb 2009 17:11:06 +0300, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>>>>
>>>>>> Nick Sabalausky wrote:
>>>>>>> "Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gmpd71$8uj$1@digitalmars.com...
>>>>>>>> Alex Burton wrote:
>>>>>>>>> I think it makes no sense to have nullable pointers in a high level language like D.
>>>>>>>> Oh, and how do you intend to make linked lists?  Or trees?  Or any
>>>>>>>> non-trivial data structure?
>>>>>>>>
>>>>>>>  Null Object Pattern:
>>>>>>> --------------
>>>>>>> class LinkedListNode(T)
>>>>>>> {
>>>>>>>     LinkedListNode!(T) next;
>>>>>>>      private static LinkedListNode!(T) _end;
>>>>>>>     static LinkedListNode!(T) end() {
>>>>>>>         return _end;
>>>>>>>     }
>>>>>>>     static this() {
>>>>>>>          _end = new LinkedListNode!(T);
>>>>>>>     }
>>>>>>> }
>>>>>>> --------------
>>>>>>
>>>>>>
>>>>>> What is "next" for the _end node?
>>>>>>
>>>>>> Andrei
>>>>>  Perhaps, 'this' (i.e. itself).
>>>>
>>>> Then there's going to be quite a few infinite loops out there...
>>>>
>>>> Andrei
>>>  No, you just need to have a private ctor:
>>
>> I meant that code that fails to check for _end when iterating through a list will never stop.
>>
>> Andrei
> 
> No, error like that will be detected at compile time (comparison against null is disallowed for non-nullable reference).

I must be misunderstanding something. At the highest level, the example given replaced the terminating node of a list (which traditionally is null) with a node that had itself as the next node.

This means that if you iterate such a list without testing for node == _end, you will have an infinite loop. This has nothing to do with types.


Andrei
February 10, 2009
"Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:gmsd6o$2h77$1@digitalmars.com...
>
> I must be misunderstanding something. At the highest level, the example given replaced the terminating node of a list (which traditionally is null) with a node that had itself as the next node.
>
> This means that if you iterate such a list without testing for node == _end, you will have an infinite loop. This has nothing to do with types.
>

------------------
class LinkedListNode(T)
{
    static this() {
         _end = new LinkedListNode!(T)(55555);
    }

    this() {
        // Prevent _next from being auto-inited to
        // a new LinkedListNode, which in turn
        // would have a _next auto-inited to a
        // new LinkedListNode, etc.
        _next = _end;
    }

    // Prevent _end._next from being auto-inited to
    // a new LinkedListNode, which in turn
    // would have a _next auto-inited to a
    // new LinkedListNode, etc.
    private this(int dummy) {
        _next = this;
    }

    private static LinkedListNode!(T) _end;
    static LinkedListNode!(T) end() {
        return _end;
    }

    private LinkedListNode!(T) _next;
    void next(LinkedListNode!(T) newNext) {
        _next = newNext;
    }
    LinkedListNode!(T) next() {
        // Prevent infinite iteration
        if(this is _end)
            throw new Exception("Iterated past the end!");
        else
            return _next;
    }
}
------------------

Note, however, that I'm not advocating this approach to linked lists or other advanced structures (since it's so much uglier than just using a nullable reference). I'm just pointing out that it's at least *possible* without using nullable references.


February 10, 2009
Nick Sabalausky wrote:
> "Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:gmsd6o$2h77$1@digitalmars.com...
>> I must be misunderstanding something. At the highest level, the example given replaced the terminating node of a list (which traditionally is null) with a node that had itself as the next node.
>>
>> This means that if you iterate such a list without testing for node == _end, you will have an infinite loop. This has nothing to do with types.
>>
> 
> ------------------
> class LinkedListNode(T)
[snip]

Oh ok, now I understand. Thanks.

Andrei