In C#2+ there's the Nullable type, one of its main purposes is to represent
null values coming from databases. Another purpose for D is for example
find(iterable) can return a Nullable!T instead of throwing an exception (or
returning -1) if no item can be found. So if seen as useful D can add a
Nullable to Phobos in less than two years from now, when dmd2 has less bugs.
A Nullable struct is not so complex, it can be added to Phobos2. Before
creating it some design decisions are necessary, here are three of them:
1) Nullable!(SomeClass) is forbidden in C#. D Nullable can do the same, but
this hurts generic code a little. An alternative is in this case to not add the
boolean field to the Nullable and make hasValue just look if the reference !is
null (so if T is a class then (Nullable!T).sizeof == T.sizeof). If object
references are allowed then writing the value field sets the hasValue boolean
to true if T is not a class reference.
2) C# forbids Nullable!(Nullable!T), D can do the same or it can make
Nullable!(Nullable!T) === Nullable!T to allow to write simpler generic code.
3) C# uses something similar to valueorInit() that returns T.init if the
hasValue property is false. D can do the same, or it can use
get(default=T.init) that returns the value if present or the given default (or
the default default). This can be a problem if a delegate is taken out of get
because in D default values are added at call point, they are not an
information stored inside the callee as in Python.
So Nullable can have the methods/properties:
value
@property hasValue
get(defaukt=T.init)
type alias of T
Reading the value if hasValue is false generates a specific exception.
An error for safety:
Nullable!int x;
int y = x; // compile ERROR
int y = x.get(); // OK
int y = x.get(5); // OK
int y = x.hasValue ? x.value : x.type.init; // OK
int y = x.hasValue ? x.value : -1; // OK
Optionally this can be accepted:
Nullable!int x;
if (x) { ...
that is equivalent to:
if (x.hasValue) { ...
But this doesn't look fully tidy to me...
---------------
So far I think Nullable can be implemented with not changes in the
language/compiler. Now some small things that can require such changes.
C# has the ?? operator (Elvis operator) that can be used to replace this:
Nullable!int x;
int y = x.hasValue ? x.value : -1; // OK
With:
Nullable!int x;
int y = x ?? -1;
In C# there is a bit of syntax sugar for:
Nullable!int x;
that can be written:
int? x;
This can be done in D too, but this can be added later too. The advantage of
this syntax sugar is to encourage programmers to use Nullables.
There is another possible bit of compiler help, to avoid most of those empty
Nullable exceptions and make Nullable a bit safer the compiler can refuse code
like:
Nullable!int result = foo();
int x = result.value;
And accept code like:
Nullable!int result = foo();
if (result.hasValue) {
int x = result.value;
...
} else {
...
}
Bye,
bearophile