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
Throwing out some more ideas, though non of this compiles right
now (and I managed to make the compiler ICE).
class Widget
{
private int x;
this(int y) { x = y; }
public @property int halfOfX() { return x / 2; }
public void printHello() { std.stdio.writeln("Hello"); }
//Error: 'this' is only defined in non-static member
functions,
//not Widget
static Widget init = new class Widget
{
@disable public override @property int halfOfX();
@disable public override void printHello();
this() { super(int.init); }
};
}
Another idea that unfortunately doesn't work due to the way
static assert works:
class Widget
{
private int x;
this(int y) { x = y; }
public @property int halfOfX() { return x / 2; }
public void printHello() { std.stdio.writeln("Hello"); }
static Widget init = new class Widget
{
//Error: static assert "Tried to access halfOfX
//property of null Widget"
override @property int halfOfX()
{
static assert(false,
"Tried to access halfOfX property of null
Widget");
}
override void printHello()
{
static assert(false,
"Tried to access halfOfX property of null
Widget");
}
this() { super(int.init); }
};
}
Is there any way to get around this?
And then there's this, which causes an ICE:
class Widget
{
private int x;
this(int y) { x = y; }
public @property int halfOfX() { return x / 2; }
public void printHello() { std.stdio.writeln("Hello"); }
static Widget init = new class Widget
{
this()
{
}
};
}