This has been standard advice since the last millennium. But you can't change it without breaking backwards compatibility.
That said, I do have several good uses for local. But not normal ones. My favorite is to use local to dynamically scope entries in a hash. I wind up using this every year or two to put in an automatic check to catch infinite recursion.
Oh really? What's wrong with $_ and since when it is?
I personally have no issues doing:
foreach @array {
chomp;
print;
}
But as soon as I have to type "$_" I make a real variable.Your example is perfectly OK.
TIMTOWTDI, really.
A specific problem that fixed this in my memory was a bug in my co-worker's code which boiled down to his looping over an array with $_, then calling a function in his loop that was in a CPAN library that assigned to $_. The result was that he wiped out his whole array.
Whenever you are calling out to code that someone else wrote, you don't know if issues like that could exist, and therefore it isn't safe to use $_. Conversely if you're writing code that someone else will call, be a good citizen and don't assign to $_ either implicitly or explicitly.
For example, the following code performs as expected, and prints "123"
use 5.016;
use warnings;
my @a = qw(1 2 3);
for (@a) {
my @b = qw(4 5 6);
for (@b) {
$_ = 1;
}
print;
}
This code works (prints "123") fine as well: use 5.016;
use warnings;
sub test {
my @b = qw(4 5 6);
for (@b) {
$_ = 1;
}
}
my @a = qw(1 2 3);
for (@a) {
test;
print;
}
The following causes a problem (prints "111"). Don't do this, it's stupid. use 5.016;
use warnings;
sub test {
$_ = 1;
}
my @a = qw(1 2 3);
for (@a) {
test;
print;
}
The moral? Buggy libraries are buggy, don't use them, or submit a fix.And yes, I both fixed my coworker's code to not use $_, and submitted a patch to the CPAN library with the bug. But the experience taught me to be cautious about $_.
I just think saying not to use $_ in real programs is a bit extreme. Truthfully, I don't use it in for loops at all, but my code invariably uses a lot of maps and greps. To throw away the expressiveness of map and grep because there may be a problem in some third party library I use at some point is too high a price for me. Especially because by the nature of how I use map and grep I think I'm less likely to run into problem code in those cases, and if I do I think it will be fairly obvious.
Second, I love it for security-related stuff where I really don't want something to escape a scope. I have a value that represents the current user I am processing a request for, which is used for security checks, and by local'ing the variable in the context of the handler, I can be very confident that it absolutely, positively will not escape into the next request.
It also turns out to mean that if you're in a code base that has some unfortunate "global" variables, that local lets you turn them into much less "global" variables, as you can local them with confidence about how it won't escape out of scope. Of course, the better solution is to not do that, or to fix it, but we don't live in a perfect world....
Perl's access control model uses a metaphor of polite permission. Without hardware enforcing memory protection, any memory protection at the language level is a modest barrier for the determined anyhow.