This has been well-known for years. People have used it for things like:
sub increment {
my $counter = 0 if 0;
++$counter
}
It works the same way as:
{
my $counter = 0;
sub increment { ++$counter }
}
It's actually a combination of various bugs that makes it work, so you shouldn't rely on the behavior. But since people have been relying on the behavior for years, it probably won't go away any time soon.
Perl 5.10 has a keyword ("state") for declaring this sort of variable explicitly, though, so there's no reason to use this pattern in new code.
What's interesting about this? There's a big, bold note in the documentation that says the result of this usage of a statement modifier is undefined, and that's exactly what happened.
I guess it's nice that the blog author is giving everyone a heads up, but this shouldn't be news to anyone who actually reads the documentation for the tools they use.
I just found it interesting because when I wrote the initial code I assumed it would work they way that seemed more intuitive to me. After I encountered that I went into the documentation to investigate but I don't think that one should be expected to read every single piece of documentation, least of all in a seemingly trivial case like this.
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.
(I've also made this comment on your blog, but it's the sort of thing people should manage to find easily so I figured it'd be ok to duplicate it)
Yea no worries, the more people that learn this the better - it took me a bit to diagnose. That was basically my understanding. It looks like the scope of the my gets a bit weird with that if(0) there.
With Perl, this is a pretty reasonable assumption to make. If you can think to do it, usually the interpreter will handle it in some reasonable fashion. How, I don't know. But it's one of the reasons that Perl has a reputation as a write-only language.
Its interesting because it breaks with the normal paradigm of lexically scoped variables. It is an exception, something that imho should be removed as quickly as possible.
Just because some behavior is documented does not imply that it is what should happen.
Perl 5.10 has a keyword ("state") for declaring this sort of variable explicitly, though, so there's no reason to use this pattern in new code.