(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