Jump to page: 1 216  
Page
Thread overview
Non-null objects, the Null Object pattern, and T.init
Jan 17, 2014
Adam D. Ruppe
Jan 17, 2014
Adam D. Ruppe
Jan 17, 2014
Walter Bright
Jan 17, 2014
Timon Gehr
Jan 17, 2014
Jacob Carlborg
Jan 17, 2014
Rikki Cattermole
Jan 17, 2014
Adam D. Ruppe
Jan 17, 2014
Rikki Cattermole
Jan 17, 2014
Peter Alexander
Jan 17, 2014
Peter Alexander
Jan 17, 2014
deadalnix
Jan 17, 2014
Peter Alexander
Jan 17, 2014
bearophile
Jan 17, 2014
inout
Jan 17, 2014
Namespace
Jan 17, 2014
Namespace
Jan 17, 2014
Michel Fortin
Jan 17, 2014
H. S. Teoh
Jan 17, 2014
Regan Heath
Jan 17, 2014
H. S. Teoh
Jan 17, 2014
H. S. Teoh
Jan 20, 2014
H. S. Teoh
Jan 17, 2014
Walter Bright
Jan 17, 2014
Artur Skawina
Jan 17, 2014
Timon Gehr
Jan 17, 2014
Jacob Carlborg
Jan 17, 2014
Meta
Jan 17, 2014
Adam D. Ruppe
Jan 17, 2014
Walter Bright
Jan 17, 2014
Adam D. Ruppe
Jan 17, 2014
Walter Bright
Jan 18, 2014
Walter Bright
Jan 18, 2014
Walter Bright
Jan 18, 2014
Michel Fortin
Jan 18, 2014
Walter Bright
Jan 18, 2014
Michel Fortin
Jan 18, 2014
Walter Bright
Jan 18, 2014
Walter Bright
Jan 18, 2014
Namespace
Jan 18, 2014
Walter Bright
Jan 18, 2014
Jacob Carlborg
Jan 18, 2014
Daniel Murphy
Jan 18, 2014
Jacob Carlborg
Jan 18, 2014
Tobias Pankrath
Jan 18, 2014
Daniel Murphy
Jan 18, 2014
Jacob Carlborg
Jan 18, 2014
Walter Bright
Jan 18, 2014
Michel Fortin
Jan 18, 2014
Walter Bright
Jan 19, 2014
Walter Bright
Jan 19, 2014
Kapps
Jan 19, 2014
Walter Bright
Jan 19, 2014
Walter Bright
Jan 19, 2014
Paolo Invernizzi
Jan 19, 2014
Walter Bright
Jan 19, 2014
Jacob Carlborg
Jan 19, 2014
bearophile
Jan 19, 2014
Michel Fortin
Jan 19, 2014
Paolo Invernizzi
Jan 18, 2014
Walter Bright
Jan 18, 2014
bearophile
Jan 18, 2014
Walter Bright
Jan 18, 2014
H. S. Teoh
Jan 18, 2014
Walter Bright
Jan 18, 2014
deadalnix
Jan 18, 2014
Walter Bright
Jan 18, 2014
Paolo Invernizzi
Jan 17, 2014
H. S. Teoh
Jan 17, 2014
Walter Bright
Jan 17, 2014
H. S. Teoh
Jan 17, 2014
Walter Bright
Jan 17, 2014
H. S. Teoh
Jan 18, 2014
Walter Bright
Jan 18, 2014
deadalnix
Jan 18, 2014
Walter Bright
Jan 18, 2014
H. S. Teoh
Jan 18, 2014
Timon Gehr
Jan 17, 2014
Michel Fortin
Jan 17, 2014
Yota
Jan 18, 2014
Michel Fortin
Jan 17, 2014
Jacob Carlborg
Jan 17, 2014
Michel Fortin
Jan 18, 2014
Adam D. Ruppe
Jan 18, 2014
deadalnix
Jan 18, 2014
Walter Bright
Jan 18, 2014
bearophile
Jan 18, 2014
Walter Bright
Jan 18, 2014
Walter Bright
Jan 19, 2014
Timon Gehr
Jan 20, 2014
Walter Bright
Jan 20, 2014
Tobias Pankrath
Jan 18, 2014
Walter Bright
Jan 18, 2014
Jacob Carlborg
Jan 18, 2014
Walter Bright
Jan 18, 2014
Namespace
Jan 18, 2014
Namespace
Jan 18, 2014
bearophile
Jan 18, 2014
Michel Fortin
Jan 18, 2014
Walter Bright
Jan 18, 2014
bearophile
Jan 19, 2014
Nicolas Sicard
Jan 18, 2014
Michel Fortin
Jan 18, 2014
bearophile
Jan 18, 2014
Walter Bright
Jan 18, 2014
Walter Bright
Jan 18, 2014
bearophile
Jan 18, 2014
bearophile
Jan 18, 2014
Walter Bright
Jan 18, 2014
bearophile
Jan 18, 2014
Walter Bright
Jan 19, 2014
Michel Fortin
Jan 18, 2014
deadalnix
Jan 18, 2014
deadalnix
Jan 19, 2014
Timon Gehr
Jan 19, 2014
Michel Fortin
Jan 19, 2014
Timon Gehr
Jan 20, 2014
Michel Fortin
Jan 20, 2014
deadalnix
Jan 20, 2014
Timon Gehr
Jan 18, 2014
Iain Buclaw
January 17, 2014
Walter and I were talking today about the null pointer issue and he had the following idea.

One common idiom to replace null pointer exceptions with milder reproducible errors is the null object pattern, i.e. there is one object that is used in lieu of the null reference to initialize all otherwise uninitialized references. In D that would translate naturally to:

class Widget
{
    private int x;
    private Widget parent;
    this(int y) { x = y; }
    ...
    // Here's the interesting part
    static Widget init = new Widget(42);
}

Currently the last line doesn't compile, but we can make it work if the respective constructor is callable during compilation. The compiler will allocate a static buffer for the "new"ed Widget object and will make init point there.

Whenever a Widget is to be default-initialized, it will point to Widget.init (i.e. it won't be null). This beautifully extends the language because currently (with no init definition) Widget.init is null.

So the init Widget will satisfy:

assert(x == 42 && parent is Widget.init);

Further avenues are opened by thinking what happens if e.g. init is private or @disable-d.

Thoughts?


Andrei
January 17, 2014
On Friday, 17 January 2014 at 01:42:38 UTC, Andrei Alexandrescu wrote:
>     static Widget init = new Widget(42);

The problem here is if it is in a mutable data segment:

Widget i; // implicitly set to init
assert(i is Widget.init); // uh oh
i.mutate();

Widget i2; // set to widget init...
assert(i is i2); // oh dear
// i2 now reflects the mutation done above!


And if the init is put in a read-only segment similar to a string buffer, we still get a segmentation fault when we try to mutate it.



I'm not necessarily against having the option, but I think it would generally be more trouble than it is worth. If you have an object that you want to guarantee is not null, make the nullable implementation

class Widget_impl {}

then define

alias Widget = NotNull!Widget_impl;

and force initialization that way.
January 17, 2014
On Friday, 17 January 2014 at 01:42:38 UTC, Andrei Alexandrescu wrote:
> Walter and I were talking today about the null pointer issue and he had the following idea.
>
> One common idiom to replace null pointer exceptions with milder reproducible errors is the null object pattern, i.e. there is one object that is used in lieu of the null reference to initialize all otherwise uninitialized references. In D that would translate naturally to:
>
> class Widget
> {
>     private int x;
>     private Widget parent;
>     this(int y) { x = y; }
>     ...
>     // Here's the interesting part
>     static Widget init = new Widget(42);
> }
>
> Currently the last line doesn't compile, but we can make it work if the respective constructor is callable during compilation. The compiler will allocate a static buffer for the "new"ed Widget object and will make init point there.
>
> Whenever a Widget is to be default-initialized, it will point to Widget.init (i.e. it won't be null). This beautifully extends the language because currently (with no init definition) Widget.init is null.
>
> So the init Widget will satisfy:
>
> assert(x == 42 && parent is Widget.init);
>
> Further avenues are opened by thinking what happens if e.g. init is private or @disable-d.
>
> Thoughts?
>
>
> Andrei

I am assuming init will be a property static function. So essentially we would be removing .init support for classes in compiler and pushing it out into Object.

I would rather if that is an option an init static function, that it would be required to have override otherwise it would be too 'magical' for me atleast.
The default can still be null.
January 17, 2014
On Friday, 17 January 2014 at 01:42:38 UTC, Andrei Alexandrescu wrote:
> Whenever a Widget is to be default-initialized, it will point to Widget.init (i.e. it won't be null). This beautifully extends the language because currently (with no init definition) Widget.init is null.

Hmm, what about derived classes? How do you check for a valid Widget given a DerivedWidget.init?

class DerivedWidget : Widget
{
    static DerivedWidget init = new DerivedWidget(...);
}

bool valid(Widget w) { return w !is Widget.init; }

DerivedWidget foo;
assert(!valid(foo)); // doesn't fire, foo is valid?


The nice thing about null is that it is the bottom type, so it is a universal sentinel value.

Also, what about interfaces? You cannot define an init for an interface. Obviously that could just be a known and accepted limitation of this proposal, but I'm not a huge fan of solutions that only work in a subset of situations. Perhaps there is a solution that I haven't thought of.


> assert(x == 42 && parent is Widget.init);

Is that meant to say "x is Widget.init"?
January 17, 2014
On 1/16/14 5:53 PM, Adam D. Ruppe wrote:
> On Friday, 17 January 2014 at 01:42:38 UTC, Andrei Alexandrescu wrote:
>>     static Widget init = new Widget(42);
>
> The problem here is if it is in a mutable data segment:
>
> Widget i; // implicitly set to init
> assert(i is Widget.init); // uh oh
> i.mutate();
>
> Widget i2; // set to widget init...
> assert(i is i2); // oh dear
> // i2 now reflects the mutation done above!

Yah, that would be expected.

> I'm not necessarily against having the option, but I think it would
> generally be more trouble than it is worth. If you have an object that
> you want to guarantee is not null, make the nullable implementation
>
> class Widget_impl {}
>
> then define
>
> alias Widget = NotNull!Widget_impl;
>
> and force initialization that way.

Noted.


Andrei

January 17, 2014
On Friday, 17 January 2014 at 01:57:24 UTC, Rikki Cattermole wrote:
> I am assuming init will be a property static function. So essentially we would be removing .init support for classes in compiler and pushing it out into Object.

I don't think a function would work without major work since that would mean adding non-blit* default construction to the language - which isn't present at all right now.
January 17, 2014
On 1/16/14 5:57 PM, Rikki Cattermole wrote:
> I am assuming init will be a property static function.

In the example above it's just a static data member.

> So essentially we
> would be removing .init support for classes in compiler and pushing it
> out into Object.
>
> I would rather if that is an option an init static function, that it
> would be required to have override otherwise it would be too 'magical'
> for me atleast.
> The default can still be null.

Override only works for nonstatic methods.


Andrei
January 17, 2014
On Friday, 17 January 2014 at 01:42:38 UTC, Andrei Alexandrescu
wrote:
> Walter and I were talking today about the null pointer issue and he had the following idea.
>
> One common idiom to replace null pointer exceptions with milder reproducible errors is the null object pattern, i.e. there is one object that is used in lieu of the null reference to initialize all otherwise uninitialized references. In D that would translate naturally to:
>
> class Widget
> {
>     private int x;
>     private Widget parent;
>     this(int y) { x = y; }
>     ...
>     // Here's the interesting part
>     static Widget init = new Widget(42);
> }
>
> Currently the last line doesn't compile, but we can make it work if the respective constructor is callable during compilation. The compiler will allocate a static buffer for the "new"ed Widget object and will make init point there.
>
> Whenever a Widget is to be default-initialized, it will point to Widget.init (i.e. it won't be null). This beautifully extends the language because currently (with no init definition) Widget.init is null.
>
> So the init Widget will satisfy:
>
> assert(x == 42 && parent is Widget.init);
>
> Further avenues are opened by thinking what happens if e.g. init is private or @disable-d.
>
> Thoughts?
>
>
> Andrei

Most object don't have a sensible init value. That is just hiding
the problem under the carpet.
January 17, 2014
On 1/16/14 6:02 PM, Peter Alexander wrote:
> On Friday, 17 January 2014 at 01:42:38 UTC, Andrei Alexandrescu wrote:
>> Whenever a Widget is to be default-initialized, it will point to
>> Widget.init (i.e. it won't be null). This beautifully extends the
>> language because currently (with no init definition) Widget.init is null.
>
> Hmm, what about derived classes? How do you check for a valid Widget
> given a DerivedWidget.init?
>
> class DerivedWidget : Widget
> {
>      static DerivedWidget init = new DerivedWidget(...);
> }
>
> bool valid(Widget w) { return w !is Widget.init; }
>
> DerivedWidget foo;
> assert(!valid(foo)); // doesn't fire, foo is valid?
>
>
> The nice thing about null is that it is the bottom type, so it is a
> universal sentinel value.

This is a good point.

> Also, what about interfaces? You cannot define an init for an interface.
> Obviously that could just be a known and accepted limitation of this
> proposal, but I'm not a huge fan of solutions that only work in a subset
> of situations. Perhaps there is a solution that I haven't thought of.
>
>
>> assert(x == 42 && parent is Widget.init);
>
> Is that meant to say "x is Widget.init"?

To clarify:

assert(Widget.init.x == 42 && Widget.init.parent is Widget.init);


Andrei

January 17, 2014
On Friday, 17 January 2014 at 02:07:08 UTC, deadalnix wrote:
> Most object don't have a sensible init value. That is just hiding
> the problem under the carpet.

That's true.

class Widget
{
    Widget parent;
    static Widget init = ???
}

How do you define init?
« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10 11