null [re: spec#]

Roman Ivanov isroman.DEL at ETE.km.ru
Sun Nov 7 07:51:20 PST 2010


On 11/7/2010 1:02 AM, Walter Bright wrote:
> Jonathan M Davis wrote:
>> Going C# or Java's route forces the programmer to initialize variables
>> even in cases where they know that it's not necessary (which is
>> annoying but may or may not be worth it),
> 
> Correct. It's not that doing flow analysis is hard, it's that it's
> impossible to do it correctly. So you wind up with wishy-washy messages
> that p "might not" be initialized, which is what the Java compiler does
> for this:
>
>   class A
>   {
>        public void foo()
>        {
>            Object p;
>            if (m)
>                 p = new Object();
>            if (m)
>                 p.toString();  // <-- p might not have been initialized
>        }
>        boolean m;
>   }
> 
> It even errors out if you write it as:
> 
>   class A
>   {
>        public void foo()
>        {
>            Object p;
>            if (m)
>                 p = new Object();
>            if (p != null)  // <-- p might not have been initialized
>                 p.toString();
>        }
>        boolean m;
>   }
> 
> Note that the error message is on the null check! 

I know what your mean, but the example is flawed:

public void foo()
{
    if (m) {
         Object p = new Object();
         p.toString();
    }
}

...

Thing is, I don't think you really _need_ flow analysis to implement
nonnulity. The simplest way is to disallow creation of unitialized
nonnull variables. I think it would work, but without some clever syntax
such rule would be painful to follow for the programmers. Things like
these would be prohibited, for example

Duck d;
if (b)
    d = new Duck();
else
    d = new DuckSubclass();

Seems like a big loss, but it really isn't.

Duck d = b ? new Duck() : new DuckSubclass();

But ternary ops are not generic, unless you chain them which is
super-ugly. Is there nothing that can fix this? Delegates probably can:

enum Dri {  one, two, three};
Dri s = Dri.two;

int x = {
    if (s == Dri.one)
        return 1;
    else if (s == Dri.two)
        return 2;
    else
        return 3;
}();

This works. I'm not sure how efficient it is, but that would solve the
issue with initialization without any path analysis. If there was a
clearer, more efficient syntax for this, it would work even better.

int x = do {
    if (s == Dri.one)
        return 1;
    else if (s == Dri.two)
        return 2;
    else
        return 3;
};


More information about the Digitalmars-d mailing list