(non)nullable types

Nick Sabalausky a at a.a
Sat Feb 14 11:27:18 PST 2009


"Denis Koroskin" <2korden at gmail.com> wrote in message 
news:op.upcaojexo7cclz at korden-pc...
> On Sat, 14 Feb 2009 11:39:17 +0300, Nick Sabalausky <a at a.a> wrote:
>
>> "Michel Fortin" <michel.fortin at michelf.com> wrote in message
>> news:gn4pl9$1217$1 at digitalmars.com...
>>> On 2009-02-13 14:01:57 -0500, "Nick Sabalausky" <a at a.a> said:
>>>
>>>>> Or use an existing syntax:
>>>>>
>>>>> Foo? foo = ...;
>>>>> if (Foo value = foo) {
>>>>> // value is a local variable that is only accessible if foo is not
>>>>> null
>>>>> } else {
>>>>> // value is not accessible here
>>>>> }
>>>>
>>>> I could live with that, but I'd prefer my suggestion because it 
>>>> wouldn't
>>>> require the creation of an extra label for what's essentially the same
>>>> variable. With your code we'd just end up with a whole bunch of:
>>>>
>>>> Foo? myObj = ...;
>>>> if (Foo nonnullMyObj = myObj) //etc...
>>>>
>>>> // or
>>>>
>>>> Foo? nullableMyObj = ...;
>>>> if (Foo myObj = nullableMyObj) //etc...
>>>>
>>>> ...Which just seems unnecessary to me.
>>>
>>> Foo? myObj = ...;
>>> if (myObj !is null)
>>> {
>>>     doSomethingWith(myObj);
>>>     myObj = null; // should this be an error?
>>> }
>>>
>>
>> --------
>> // This (a more generalized case of above)...
>>
>> Foo? myObj = ...;
>> if(myObj !is null)
>> {
>>     bar1(myObj);
>>     if(blah1 > blah2)
>>         myObj = null; // Yes, error
>>     bar2();
>> }
>>
>> // ...would change to this...
>>
>> Foo? myObj = ...;
>> bool turnToNull=false;
>> if(myObj !is null)
>> {
>>     bar1(myObj);
>>     if(blah1 > blah2)
>>         turnToNull = true;
>> }
>> if(turnToNull)
>> {
>>     myObj = null;
>>     bar2();
>> }
>> --------
>>
>>> And what about:
>>>
>>> Foo? myObj = ...;
>>> while (myObj !is null)
>>>     myObj = myObj.next;
>>>
>>
>> --------
>> Foo? myObj = ...;
>> while(true)
>> {
>>     if(myObj.next !is null)
>
> Dang! NullPointerException, because you never checked myObj against null
>
>>         myObj = myObj.next;
>>     else
>>         break;
>> }
>> myObj = null; //this line optional
>>
>> // Or, if you don't like "while(true)",
>> // you could use a "bool done" flag.
>> --------
>>

I blame fatigue ;)

--------
Foo? myObj = ...;
if(myObj !is null)
{
    while(true)
    {
        if(myObj.next !is null)
            myObj = myObj.next;
        else
            break;
    }
}
myObj = null; //this line optional
--------

>
> I don't think code flow analysis the way you suggest is useful. I 
> certainly don't want my variable types to be changed at some point after 
> null-check.
>

I'm not sure if we're on the same page here. What I was thinking about code 
flow analysis was this:

Foo? maybeGetObj() {...}
void takesAFoo(Foo f) {...}

Foo? f = maybeGetObj(); // Ok, f *is* permanently "Foo?"
f.mFunc(); // Illegal, might be null
takesAFoo(f); // Illegal, might be null

// Tells compiler f is now implicitly convertable to "Foo"
if(f !is null)
{
    f.mFunc(); // Ok
    takesAFoo(f); // Ok

    // With flow-analysis, this is ok and tells
    // compiler f is no longer implicitly
    // convertable to "Foo"
    f = maybeGetObj();
    f.mFunc(); // Illegal
    takesAFoo(f); // Illegal

    f = new Foo(); // now implicitly convertable to "Foo"
    f.mFunc(); // Ok
    takesAFoo(f); // Ok

    // Ok, but possible warning that the condition's
    // result will always be the same (true in this case).
    if(f !is null) {...}

    f = null; // no longer implicitly convertable to "Foo"
}
else // f is still *not* implicitly convertable to "Foo"
{
    f = new Foo();  // now implicitly convertable to "Foo"
}
// Depending which branch of the if was taken,
// f might be implicitly convertable to "Foo",
// or it might not be. So, from here, assume
// that it *isn't* implicitly convertable to "Foo".

Foo f2=...; // Ok, f2 *is* permanently "Foo"

 // Illegal, f2 *is* "Foo"
f2 = null;

// Error, comparison of incompatible types
if(f2 !is null) {...}

> Code flow analysis would be nice to have, but in a different way:
>
> Foo b; // not initialized, can not be read yet
>
> if (condition) {
>    b = createFoo(42);
> } else if (otherCondition) {
>    b = new Foo();
> } else {
>    // return b; // error, b is write only
>    return;
> }
>
> // b is both read/write accessible at this point
>

Agreed, that would be nice to have.





More information about the Digitalmars-d mailing list