(non)nullable types
Christopher Wright
dhasenan at gmail.com
Wed Feb 18 15:13:34 PST 2009
Daniel Keep wrote:
>
> Christopher Wright wrote:
>> One problem here is static constructors. They're supposed to run in
>> import order, I believe, so if you do this:
>>
>> module A;
>> Object o;
>> static this () { o = new Object; }
>>
>> module B;
>> import A;
>> static this () { writeln(o); }
>>
>> That should be safe. I think.
>>
>> Class member variables are also problematic. It's probably going to be
>> annoying to make sure each nullable variable gets initialized in every
>> constructor. I could push that off to runtime, of course, but that isn't
>> so great.
>>
>> Struct member variables are the killer, unless you have a struct
>> constructor.
>
> Mmm... non-nullable types would also be the only type in D that cannot
> have it's own initialiser assigned to it.
You could have the compiler use the default constructor to create an
instance and assign that to Type.init, but that is evil.
> This is actually something I ran across trying to make a non-nullable
> struct; it can't be done because you can't force a variable to be
> non-default initialised.
>
> I'm not sure what the solution would be. A few thoughts:
>
> * Allow types to be flagged, within the compiler, as being "must-set."
> This includes all non-nullable types AND any aggregates that contain
> non-nullable types. If they're local variables, they have to be
> assigned to at declaration, and if they're members, the have to be
> assigned to within the constructor.
Determining this is a bit ugly...I think I said that.
> * Make these types the exception and don't give them an init property.
> Generic code will either have to test for its absence, fail for
> non-nullable types, or be written differently.
No init property by default, but you could easily supply one. It
wouldn't be CTFE-friendly, though.
> * Alternately, have an init property which is invalid and can't be
> assigned. Probably worse since you can't easily test for it.
You can; see below. But the test isn't obvious.
> * If using the T? syntax to mean "nullable T," generic code could be
> written to use T? for all classes, then do the conversion to
> non-nullable at return time.
Nullable seems to be a storage class. T? will be inconsistent as such.
Additionally, I am certainly not going to implement nullable value
types, and T? is the C# syntax for nullable value types, so that is
inconsistent.
One advantage of using "nullable T" rather than "T?" is IsExpressions:
static if (is (T == nullable)) ...
The alternative will probably be necessary, as well:
static if (is (T U == nullable U)) ...
> * What should the following output?
>
> class T {}
>
> static if( is( T? : T ) ) pragma(msg, "T? : T");
> static if( is( T : T? ) ) pragma(msg, "T : T?");
T is implicitly convertible to nullable(T). There is some debate on
whether the opposite should be allowed. So that will either print:
T : T?
or:
T? : T
T : T?
More information about the Digitalmars-d
mailing list