On 7/6/10, bearophile <[email protected]> wrote:
> 1) Nullable!(SomeClass) is forbidden in C#.

I figure a Nullable struct would just alias the original type if T t;
t = null; already compiles. So a nullable pointer, class, or Nullable
is just a no-op. This would cover your cases 1 and 2 with a simple
rule.

> 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...

Blargh, what I'd want is

if(x is null)


An implementation that might work is

=============

template Nullable(T) {
        static if(is(typeof( {
                T t;
                t = null;
        }))) {
                alias T Nullable; // if it is already nullable, do nothing 
special
        }
        else
        {
                struct Nullable {
                        T value;
                        T* hasValue = null; // i guess this could be boolean too

                        bool opCast(A)() if(is(A == bool)) { // for if(x)
                                return !(hasValue is null);
                        }

                        typeof(this) opAssign(T v) { // should be ok assigning 
known not-null values
                                value = v;
                                hasValue = &value;
                                return this;
                        }

                        typeof(this) opAssign(typeof(this) t) { // Nullable!T = 
Nullable!T
should always be good
                                value = t.value;
                                if(t.hasValue)
                                        hasValue = &value;
                                else
                                        hasValue = null;
                                return this;
                        }

                        typeof(this) opAssign(void* nullptr) { // so literal 
null assignment works
                                assert(nullptr is null);
                                hasValue = null;
                                return this;
                        }
                }
        }
}

// below is a kind of unittest

class A {}

import std.stdio;

void main() {
        A a1;
        Nullable!A a2;

        a1 = a2;
        a2 = a1; // compatible; types are aliases

        Nullable!(Nullable!A) a3;

        a1 = a3; // still compatible, aliases

        int* b1;
        Nullable!(int*) b2;

        b1 = b2;
        b2 = b1; // aliases again

        int c1;
        Nullable!(int) c2;

        assert(!c2.hasValue); // it should start null

        //c1 = c2; // doesn't compile; they are different types
        c2 = c1; // does compile, and set to non-null implicitly

        assert(c2.hasValue); // just assigned to it; shouldn't be bull

        c2 = null; // should compile, set to null

        assert(!c2.hasValue);

        Nullable!(Nullable!int) c3;

        c3 = 10; // should be fine

        c2 = c3; // should compile

//      c1 = c3; // should not and does not

        if(c2) // same as if(c2.hasValue)
                assert(0);
        else
                writefln("value is %d", c2.value);
}

==============



> C# has the ?? operator (Elvis operator) that can be used to replace this:
> int y = x ?? -1;

Meh, the regular ternary works fine, or this could be a member function:

x.get(-1); // gets if not null, returns -1 if it is null

x itself is a struct, so it can never be null, so no need to worry
about x.get throwing a segfault.


> 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.

Gah, Nullable!T is perfectly fine. I don't even know if you actually
want to encourage people to use nullables; they shouldn't be needed
all that often says my gut. Better to avoid things being null if
possible.

Reply via email to