Re: RFC 12 (v2) variable usage warnings
On Wed, 20 Sep 2000 12:30:26 -0600, Tom Christiansen wrote: $a = undef; You have initialized it to undef. Solution: Remove all references from the language to defined and undef. Quite the reverse. Simply assume that uninitialized variables in Perl simply don't exist, that all variables (values) are ininitalized, but some of them to undef. Therefore the word "initialized", when talking about Perl, is meaningless. Replace all occurences of the (sub)word "initialized" with "defined", in all of the documentation and in all error messages, in particular in "Use of uninitialized value%s". Look at what perldiag says about it: Use of uninitialized value%s (W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables. Look ma. The message talks about "uninitialized". The explanation only talks about "defined"/"undefined". The message should match the description. -- Bart.
Re: RFC 12 (v2) variable usage warnings
On Wed, 20 Sep 2000, Steve Fink wrote: 1 my ($x, $y, $z); 2 $z = 1; 3 my $logfile = "/tmp/log"; 4 $x = 1 if cond(); 5 print $x+$y; 6 undef $z; 7 print $z; -- use of uninitialized variable $y in line 5 (compile time) -- possible use of uninitialized variable $x in line 5 (compile time) -- variable $logfile defined in line 3 but never used (compile time) -- use of undefined value in line 7 (run time) Couldn't the error on line 7 be detected at compile time as well? After all, there is no execution path which will result in $z having a defined value. Dave
Re: RFC 12 (v2) variable usage warnings
On Wed, 20 Sep 2000, Eric Roode wrote: foo(); print $x; Generate a warning, or not? Which one? Remember, foo() may initialize $x. My suggest (FWIW) would be that, if there is no execution path which leads to $x being defined in the second line, then a "Use of uninit'd variable $x" warning should be thrown at compile time. If there is at least one path that will result in $x being defined AND at least one path that will result in it being undefined, the compile-time warning could be something like "Possible use of undefined variable $x" or "Not all execution paths leave $x defined". Dave
Re: RFC 12 (v2) variable usage warnings
Dave Storrs wrote: On Wed, 20 Sep 2000, Eric Roode wrote: foo(); print $x; Generate a warning, or not? Which one? Remember, foo() may initialize $x. My suggest (FWIW) would be that, if there is no execution path which leads to $x being defined in the second line, then a "Use of uninit'd variable $x" warning should be thrown at compile time. If there is at least one path that will result in $x being defined AND at least one path that will result in it being undefined, the compile-time warning could be something like "Possible use of undefined variable $x" or "Not all execution paths leave $x defined". Makes sense. Just have to be careful to describe all this stuff without mixing together initialization vs definedness, globals vs lexicals, flow control analysis vs counting occurrences, compile time vs run time, and definite problems vs possible problems. Makes my head hurt.
Re: RFC 12 (v2) variable usage warnings
Allow me to throw another log on the fire: my $x; if (something) { $x = 1; } my $y = $x; This would give a compile-time warning under your RFC, warning the user of a possibly uninitialized $x. Okay. Next: my $x; if (something) { $x = 1; } else { $x = 2; } my $y = $x; Would this give the same warning? Would it notice that $x is set in both branches of the condition? Worse: my $x; if (something) { $x = 1; } if (!something) { $x = 2; } my $y = $x; I presume this would generate a warning under your RFC, right? Since I would guess the compiler shouldn't be required to notice that one condition is the inverse of the other? I'm not sure I like the above construct not behaving identically to the second case (if...else...) above... Moving on: my $x; if (thing1) { $x = 1; } elsif (thing2) { $x = 2; } elsif (thing3) { $x = 3; } else { $x = 4; } my $y = $x; Warnings, or no? How about: my ($x, $i); for ($i=0; $i10; $i++) { $x .= $i; } my $y = $x; Now, I can look at that and see that $x will be '0123456789', but the compiler can't be expected (imho) to know whether the loop condition will ever execute, so under your RFC it will generate a "possibly uninitialized" warning, right? -- Eric J. Roode, [EMAIL PROTECTED] print scalar reverse sort Senior Software Engineer'tona ', 'reh', 'ekca', 'lre', Myxa Corporation'.r', 'h ', 'uj', 'p ', 'ts';
Re: RFC 12 (v2) variable usage warnings
Eric Roode wrote: Allow me to throw another log on the fire: my $x; if (something) { $x = 1; } my $y = $x; This would give a compile-time warning under your RFC, warning the user of a possibly uninitialized $x. Okay. Next: Yes. my $x; if (something) { $x = 1; } else { $x = 2; } my $y = $x; Would this give the same warning? Would it notice that $x is set in both branches of the condition? Yes, it would notice this and not warn. All paths of flow control leading to the final statement contain an initialization. Worse: my $x; if (something) { $x = 1; } if (!something) { $x = 2; } my $y = $x; I presume this would generate a warning under your RFC, right? Yes. And not necessarily a spurious one: consider using $dsoifjd++ for 'something'. Since I would guess the compiler shouldn't be required to notice that one condition is the inverse of the other? It would also have to prove that the value of 'something' does not change from one call to the next. I'm not sure I like the above construct not behaving identically to the second case (if...else...) above... The "possibly" version would need to be optional (or more optional) than the others. As soon as it gave me even one spurious warning, I would immediately turn it off except to periodically turn on all warnings full blast to get a "lint"-like effect. Moving on: my $x; if (thing1) { $x = 1; } elsif (thing2) { $x = 2; } elsif (thing3) { $x = 3; } else { $x = 4; } my $y = $x; Warnings, or no? No warnings. How about: my ($x, $i); for ($i=0; $i10; $i++) { $x .= $i; } my $y = $x; Now, I can look at that and see that $x will be '0123456789', but the compiler can't be expected (imho) to know whether the loop condition will ever execute, so under your RFC it will generate a "possibly uninitialized" warning, right? Right. We could stray from correctness here and assume any for loop is executed at least once, but I'd rather not -- this is the code pattern where it is most useful (because often the programmer doesn't notice that, in fact, that for or while loop might not execute, in some weird case.) In this particular case, it might not be unreasonably difficult to ask the question of "is COND true immediately after INIT in for(INIT; COND; INCR)?" But the compiler certainly won't be that smart in version 1.
Re: RFC 12 (v2) variable usage warnings
Tom Christiansen wrote: The warning for the use of an unassigned variable should be "use of uninitialized variable C$x". The problem with that idea, now as before, is that this check happens where Perl is looking at a value, not a variable. Even were it possible to arduously modify Perl to handle explicitly named simple variables, there's much more to consider. if ( fx() == fy() ) { } For one. --tom Yes, we've been through this before. :-) And now, as before, that's not what the RFC is saying. Your fx() example would produce the warning "use of undefined value". No variable name. Same for the code Cmy @x = (1,2,3); print $x[32]. I am not changing the existing warning at all, just rewording it from "uninitialized" to "undefined", because that's what it is. 'Initialized' means you've assigned something to it at least once; undefined means defined() returns false. I am merely suggesting that the compiler detect, when it can, that you're trying to use the value of a variable without ever having assigned a value to that variable. And in THAT message, you had better know the name of the variable, since it's the basis of the analysis. And yes, it only handles simple named variables. Example: 1 my ($x, $y, $z); 2 $z = 1; 3 my $logfile = "/tmp/log"; 4 $x = 1 if cond(); 5 print $x+$y; 6 undef $z; 7 print $z; -- use of uninitialized variable $y in line 5 (compile time) -- possible use of uninitialized variable $x in line 5 (compile time) -- variable $logfile defined in line 3 but never used (compile time) -- use of undefined value in line 7 (run time) I'll add this example to the RFC.
Re: RFC 12 (v2) variable usage warnings
And what about $$x? Dang, are we back to this incredible confusion about what it is to be defined in Perl.? undef $a; That is now UNINITIALIZED. So is this: $a = undef; You have initialized it to undef. There is no reasonable difference. Solution: Remove all references from the language to defined and undef. People just aren't smart enough to understand them. Change defined() to read has_a_valid_initialized_scalar_value(). Change undef() to "operator_to_uninitialize_a_variable". Touch luck on the chumps who can't type well. They pay for their brothers' idiocy. repeat until blue: INITIALIZED == DEFINED UNINITIALIZED == UNDEFINED --tom
Re: RFC 12 (v2) variable usage warnings
Steve Fink wrote: I am merely suggesting that the compiler detect, when it can, that you're trying to use the value of a variable without ever having assigned a value to that variable. And in THAT message, you had better know the name of the variable, since it's the basis of the analysis. And yes, it only handles simple named variables. Um, "when it can"? Isn't this considered a Hard Problem by the computer scientists? Example: 1 my ($x, $y, $z); 2 $z = 1; 3 my $logfile = "/tmp/log"; 4 $x = 1 if cond(); 5 print $x+$y; 6 undef $z; 7 print $z; -- use of uninitialized variable $y in line 5 (compile time) -- possible use of uninitialized variable $x in line 5 (compile time) -- variable $logfile defined in line 3 but never used (compile time) -- use of undefined value in line 7 (run time) How about: foo(); $x = 1 unless defined($x); print $x; Generate a warning, or not? Or: foo(); print $x; Generate a warning, or not? Which one? Remember, foo() may initialize $x. -- Eric J. Roode, [EMAIL PROTECTED] print scalar reverse sort Senior Software Engineer'tona ', 'reh', 'ekca', 'lre', Myxa Corporation'.r', 'h ', 'uj', 'p ', 'ts';
Re: RFC 12 (v2) variable usage warnings
Eric Roode wrote: Steve Fink wrote: I am merely suggesting that the compiler detect, when it can, that you're trying to use the value of a variable without ever having assigned a value to that variable. And in THAT message, you had better know the name of the variable, since it's the basis of the analysis. And yes, it only handles simple named variables. Um, "when it can"? Isn't this considered a Hard Problem by the computer scientists? The halting problem is unsolvable. That doesn't mean you can't figure out whether the complete program $x = 1 halts. But that doesn't even matter that much here; I'm saying that if the compiler can definitely determine that you are using an uninitialized variable, it should warn. If you're using something that appears like it might be uninitialized, but can't be proven either way without solving that pesky halting problem, then it (if you ask it) says "you might have screwed up." 90% of the time, it's right -- if the right set of freak occurrences happen, you really do use the value of an uninitialized variable. As an example, this may produce a spurious warning: $y = 1 if $x; $y = 2 if ! $x; ...because the compiler is unable to be sure that ($x) || (!$x) is definitely true. (And in fact, it might not be in the presence of tying. Which is why, when doing this sort of thing, compilers usually completely ignore the actual conditions being tested, and assume that they're independent and sometimes true, sometimes false.) Example: 1 my ($x, $y, $z); 2 $z = 1; 3 my $logfile = "/tmp/log"; 4 $x = 1 if cond(); 5 print $x+$y; 6 undef $z; 7 print $z; -- use of uninitialized variable $y in line 5 (compile time) -- possible use of uninitialized variable $x in line 5 (compile time) -- variable $logfile defined in line 3 but never used (compile time) -- use of undefined value in line 7 (run time) How about: foo(); $x = 1 unless defined($x); print $x; Generate a warning, or not? $x is a global. The compiler cannot detect all possible assignments to or accesses of globals, so it never warns about them. If you inserted my $x at the top of that code, it would most likely produce the "possible use" warning. Or not; this is a simple enough case that it might be able to infer the right answer. I am certainly not saying that the "possible use" warning should be enabled by default. But please, argue over that one separately from the others. It's the most likely to annoy. Or: foo(); print $x; Generate a warning, or not? Which one? Remember, foo() may initialize $x. Same thing. If $x is lexical, it gives a definite warning. If $x is a global, it says nothing. You're right; I need to point this out in the RFC.
Re: RFC 12 (v2) variable usage warnings
But that doesn't even matter that much here; I'm saying that if the compiler can definitely determine that you are using an uninitialized variable, it should warn. ... $x is a global. The compiler cannot detect all possible assignments to or accesses of globals, so it never warns about them. If you inserted my $x at the top of that code, it would most likely produce the "possible use" warning. Or not; this is a simple enough case that it might be able to infer the right answer. I am certainly not saying that the "possible use" warning should be enabled by default. But please, argue over that one separately from the others. It's the most likely to annoy. Or: foo(); print $x; Generate a warning, or not? Which one? Remember, foo() may initialize $x. Same thing. If $x is lexical, it gives a definite warning. If $x is a global, it says nothing. You're right; I need to point this out in the RFC. Careful: sub ouch { my $x; my $fn = sub { $x++ }; register($fn); print $x; } --tom
Re: RFC 12 (v2) variable usage warnings
Tom Christiansen wrote: And what about $$x? Dang, are we back to this incredible confusion about what it is to be defined in Perl.? undef $a; That is now UNINITIALIZED. So is this: $a = undef; You have initialized it to undef. There is no reasonable difference. Solution: Remove all references from the language to defined and undef. People just aren't smart enough to understand them. Change defined() to read has_a_valid_initialized_scalar_value(). Change undef() to "operator_to_uninitialize_a_variable". Touch luck on the chumps who can't type well. They pay for their brothers' idiocy. repeat until blue: INITIALIZED == DEFINED UNINITIALIZED == UNDEFINED Thank you, that's a better way of describing part of the intent of this RFC. I want to distinguish between variables that are uninitialized, and expressions whose values are undefined. my $x; # $x is uninitialized. Also, the value of $x is undefined. undef $x; # $x has now been initialized. The value of $x is still undefined. This is *not* adding a new sort of value to perl. It is adding a different state for the compiler to think of a variable as being in. Initialization of a variable means you've done something that influenced the value of that variable -- either by setting it, or blowing it away and making it undefined. You aren't interpreting the last part of the DESCRIPTION section ("you need to do my $x= undef") as meaning that my $x; and my $x = undef; have a runtime difference, are you? I think this is confusing some people, and I really shouldn't say "you would need to" do anything different; I meant "you would need to say my $x = undef if you have this warning turned on and you don't want to see it."
Re: RFC 12 (v2) variable usage warnings
Anything else? Any opinion on whether eval "" should do what it does now, and be invisible for the purposes of this analysis; or if it should be assumed to instead both use and initialize all visible variables? The former produces more spurious warnings, the latter misses many errors. You have to assume eval STRING can do anything. --tom
Re: RFC 12 (v2) variable usage warnings
Tom Christiansen wrote: Anything else? Any opinion on whether eval "" should do what it does now, and be invisible for the purposes of this analysis; or if it should be assumed to instead both use and initialize all visible variables? The former produces more spurious warnings, the latter misses many errors. You have to assume eval STRING can do anything. --tom "have to"? Perl5 doesn't. % perl -we '$x = 3; $v = "x"; eval "\$$v++"' Name "main::x" used only once: possible typo at -e line 1. I'd rather think of it as a cost-benefit tradeoff.
Re: RFC 12 (v2) variable usage warnings
Tom Christiansen wrote: Anything else? Any opinion on whether eval "" should do what it does now, and be invisible for the purposes of this analysis; or if it should be assumed to instead both use and initialize all visible variables? The former produces more spurious warnings, the latter misses many errors. You have to assume eval STRING can do anything. --tom "have to"? Perl5 doesn't. You mean "perl". % perl -we '$x = 3; $v = "x"; eval "\$$v++"' Name "main::x" used only once: possible typo at -e line 1. Non sequitur. And no, I don't have time.
Re: RFC 12 (v2) variable usage warnings
Tom Christiansen wrote: Tom Christiansen wrote: Anything else? Any opinion on whether eval "" should do what it does now, and be invisible for the purposes of this analysis; or if it should be assumed to instead both use and initialize all visible variables? The former produces more spurious warnings, the latter misses many errors. You have to assume eval STRING can do anything. --tom "have to"? Perl5 doesn't. You mean "perl". % perl -we '$x = 3; $v = "x"; eval "\$$v++"' Name "main::x" used only once: possible typo at -e line 1. Non sequitur. And no, I don't have time. It is relevant in that perl's existing behavior has proven to be useful even though the implementation is not correct. The correct implementation would not have issued the above warning, because an eval"" was present in the code. However, the correct implementation would also fail to warn in many legitimate cases. The current heuristic seems to strike a pretty good balance: % perl -le '$x = 3; eval "\$x++"' (no warning issued)
Re: RFC 12 (v2) variable usage warnings
Have a nice day. And thanks for all the fish.
Re: RFC 12 (v2) variable usage warnings
On Wed, Sep 20, 2000 at 07:20:44PM -0700, Steve Fink wrote: Tom Christiansen wrote: Steve Fink wrote: % perl -we '$x = 3; $v = "x"; eval "\$$v++"' Name "main::x" used only once: possible typo at -e line 1. Non sequitur. And no, I don't have time. It is relevant in that perl's existing behavior has proven to be useful even though the implementation is not correct. I think Tom's point is that the eval has nothing to do with what you're showing. [~] $ perl -we '$x = 3; $v = "x"; eval "\$$v++"' Name "main::x" used only once: possible typo at -e line 1. [~] $ perl -we '$x = 3; $v = "x"; $$v++' Name "main::x" used only once: possible typo at -e line 1. The correct implementation would not have issued the above warning, because an eval"" was present in the code. However, the correct implementation would also fail to warn in many legitimate cases. The current heuristic seems to strike a pretty good balance: % perl -le '$x = 3; eval "\$x++"' (no warning issued) [~] $ perl -wle'$x = 3; eval "\$x++"' Name "main::x" used only once: possible typo at -e line 1.
Re: RFC 12 (v2) variable usage warnings
The warning for the use of an unassigned variable should be "use of uninitialized variable C$x". The problem with that idea, now as before, is that this check happens where Perl is looking at a value, not a variable. Even were it possible to arduously modify Perl to handle explicitly named simple variables, there's much more to consider. if ( fx() == fy() ) { } For one. --tom