Nullable!T

bearophile bearophileHUGS at lycos.com
Tue Jul 6 04:57:03 PDT 2010


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


More information about the Digitalmars-d mailing list