On 11/7/2010 10:51 AM, Roman Ivanov wrote: > 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; > };
OF course, the code above assumes that Duck is unnulable. I didn't want to make my own syntax for it, because it would obfuscate the example.