Interesting Perl Behavior
May 30, 2008 – 2:56 pmI ran into this problem a while back and wanted to share it. It was a bit unintuitive but documentd so I guess I shouldn’t be surprised by the results. Hopefully this will help someone else avoid this pitfall.
It looks as if declaring a variable with the “my” statement but then guarded with an “if” statement causes the scope of the variable to be global – note that the “use strict ‘vars’;” pragma does not give an error in this case.
#!/usr/bin/perl -w
use strict ‘vars’;sub foo{
my $val = 0 if (0);
$val = 1 unless defined($val);
print “Val: $val\n”;
$val = 2;
}foo();
foo();
The output of this call gives:
Val: 1
Val: 2
Although the expected result would seem to be:
Val: 1
Val: 1
Using Google, I found the following nugget from perlsyn:
NOTE: The behaviour of a my statement modified with a statement modifier conditional or loop construct (e.g. my $x if … ) is undefined. The value of the my variable may be undef, any previously assigned value, or possibly anything else. Don’t rely on it. Future versions of perl might do something different from the version of perl you try it out on. Here be dragons.
http://perldoc.perl.org/perlsyn.html#Statement-Modifiers

View Comments to “Interesting Perl Behavior”
It seems like something like “(my if (0)) $val = 0″ is going on. It’s weird.
By Ricardo on Aug 5, 2008
That’s a -sort of- bug.
perl 5.10 actually throws a warning when you trip it, and provides a ‘state $x’ keyword that provides the same functionality as ‘my $x if 0′ safely.
The basic problem is that the ‘my’ causes a lexical pad entry to be generated at compile time, but because the if 0 prevents the statement running at runtime it doesn’t get reinitialised on your way round the loop.
By Matt S Trout on Aug 5, 2008
from http://perldoc.perl.org/perlsyn.html
Cheers,
Z.
By Zbigniew Lukasiak on Aug 5, 2008
They’re not global. They’re still limited in scope. The value just doesn’t get reset when the same scope is entered more than once. Although known for years, it’s been kept because, instead of reporting it as a bug, people started using this to implement static variables. It certainly wasn’t smart, but that’s what happened, and now we’re stuck with it. Perl 6 will probably fix it.
By Mark Tiefenbruck on Aug 5, 2008