Is the other-kind-of-null really necessary in Nullable and Variant?
Idan Arye
GenericNPC at gmail.com
Sun Apr 28 09:33:18 PDT 2013
When you use `std.typecons.Nullable` with a type that already
accept `null` values, you get two types of nulls - the
`Nullable`'s null state the the regular type's `null`:
Nullable!string a;
writeln(a.isNull()); //prints "true"
a = null;
writeln(a.isNull()); //prints "false"
a.nullify();
writeln(a.isNull()); //prints "true"
There is another version of Nullable where instead of a boolean
specifying if the value is null or not, you set a value to act as
the null value. If we set that null value to D's `null`, we can
get the previous example to work as expected:
Nullable!(string, null) a;
writeln(a.isNull()); //prints "true"
a = null;
writeln(a.isNull()); //prints "true"
a.nullify();
writeln(a.isNull()); //prints "true"
What I suggest is to check if the type passes to `Nullable`
accepts `null`, and if so - alias it to the second template with
`null` as it's null value.
As an added benefit, this will allow us to make null assignment
to `Nullable` possible. The way Phobos is now it's tricky - if I
write:
Nullable!string a = null;
Should `a` be D's `null` or a nullified `Nullable`? This is too
confusing, and a uniform null state would solve this conflict.
`std.variant.Variant` is more tricky:
Variant a;
Variant b = cast(string) null;
Variant c = cast(Object) null;
writeln(a == b); //prints "false"
writeln(a == c); //prints "false"
writeln(b == c); //prints "false"
writeln(b.convertsTo!Object()); //prints "false"
writeln(c.convertsTo!string()); //prints "false"
writeln(a.convertsTo!string()); //throws VariantException
And even more surprising:
writeln(c == c); //prints "false"
Although:
writeln(a == a); //prints "true"
writeln(b == b); //prints "true"
And even:
Object o1=null;
Object o2=null;
writeln(o1 == o2); //prints "true"
Again, there is no reason to have all those different types of
no-value - a null is a null is a null. a `Variant` should have a
single null value, which is also the default value, and whenever
it is assigned to `null` it should change back to that value
without caring about the type. That also mean that a `Variant`
storing a null value should implicitly convert to *any* type that
accept `null`(when using `get`, `coerce` and `convertsTo`).
I can probably implement this myself, but I want to hear the
community's opinion before I start hacking.
More information about the Digitalmars-d
mailing list