Is the other-kind-of-null really necessary in Nullable and Variant?

Simen Kjaeraas simen.kjaras at gmail.com
Mon Apr 29 11:20:17 PDT 2013


On 2013-04-29, 19:57, Idan Arye wrote:

> On Monday, 29 April 2013 at 16:14:02 UTC, deadalnix wrote:
>> On Monday, 29 April 2013 at 16:02:11 UTC, Idan Arye wrote:
>>> On Monday, 29 April 2013 at 15:39:47 UTC, Simen Kjaeraas wrote:
>>>> On 2013-04-29, 17:34, Idan Arye wrote:
>>>>
>>>>> On Monday, 29 April 2013 at 12:23:04 UTC, deadalnix wrote:
>>>>>> On Sunday, 28 April 2013 at 16:33:19 UTC, Idan Arye wrote:
>>>>>>> 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"
>>>>>>>
>>>>>>
>>>>>> All types should be non nullable. Problem solved.
>>>>>
>>>>> *All* types? Even object references and pointers?
>>>>
>>>> That would be nice, yes.
>>>
>>> And what would they be initialized to? When you write:
>>>    Object obj;
>>> what will `obj` refer to?
>>>
>>> Also, what about the C&C++ interface? Without null values, how can you  
>>> use an extern function that accepts or returns pointers?
>>
>> Data flow analysis can smash your face if you try to use that before  
>> initializing it. In fact, this is already done in many languages.
>
> The point is that you are forcing ref variables to point to data, even  
> in paths where there is no data for them to point to.
>
> Let's say we have something like:
>
>      MyClass myObject;
>      auto myVar1=DEFAULT_VALUE_FOR_MY_VAR_1;
>      bool objectCreated=false;
>      if(myCondition()){
>          myObject=new MyClass(/*some arguments*/);
>          objectCreated=true;
>          myVar1=myObject.calculateSomething();
>      }
>      auto myVar2=calculateSomethingElse(myVar1);
>      if(objectCreated){
>          myObject.doSomething(myVar2);
>      }
>      doSomethingElse(myVar2);
>
> It would be nice to create `myObject` in the second `if`, right before  
> we use it, but this is not possible, since if `myCondition` is `true`  
> and we do allocate `myObject`, we need to use it to calculate `myVar2`.  
> And we can't pull the call for `myObject.doSomething` to the first `if`  
> either - because we need to calculate `myVar2` before we use it. So, why  
> not bring the calculation of `myVar2` into the first `if` as well?  
> Because we need it for `doSomethingElse`, which should be invoked  
> whether or not we allocate `myObject`!
>
> As humans, we can easily see that if we didn't allocate `myObject` that  
> will also mean that `objectCreated` remains false, and therefore the  
> program will not enter the second `if`. I would like to see a data flow  
> analysis mechanism that figures that out - and that's a simple case!
>
> If `myObject` was `int` it would be easy - we could initialize it to `0`  
> at declaration. But object references are not that simple - if you take  
> away `null`, what will you init `myObject` to? Remember - it needs to be  
> an instance of `MyClass` or of a subclass of `MyClass`. That means that:
> a) You have to allocate memory for an object you will not use.
> b) You need to call a constructor, that might have side-effects.
> c) You end up with an object that has a meaningless state.
>
> Now, let's look at that meaningless object we created. What if `MyClass`  
> has fields which are object references themselves? They can't be in the  
> "uninitialized state" - I would like to see the data flow analysis  
> mechanism that can follow that! So, that means we need to set them to  
> meaningless objects as well.
>
> Now, consider implementing a linked list.

Now, consider the fact we have Nullable in Phobos.

-- 
Simen


More information about the Digitalmars-d mailing list