That seems bizarre, to me.
To me as well. $_ was designed for repeated use as a temporary and to
be used in a number of string-processing functions. It's so
convenient, whether in a sub or elsewhere, to do
chomp;
s/\r+$//; # not sure this is needed in modern Perl
next if ! s/^\.\.\. //;
if (s/^Root // || s/^AltRoots\d+ //) {
push @roots, $_;
} elsif (my ($depot, $workspace) = s!^View\d+ (//depot/.*) (//.*)$!!) {
...
}
(That's code off the top of my head, a contrived example.) Of course
I could "my" a variable, but then I'd have to drop it in 6 different
places.
To *my* mind, $_ belongs to some very small block: a for or while
(<>) loop a few lines long, or a map or grep expression or
block. These blocks might occur all over the place, but they all set
up their own (localised) values for $_, so they don't affect each
other.
Citations:
"man perlsyn" says that a foreach loop always localizes its control
variable,
Otherwise, the variable is implicitly local to the loop and
regains its former value upon exiting the loop. If the variable
was previously declared with "my", it uses that variable instead
of the global one, but it's still localized to the loop. This
implicit localisation occurs only in a "foreach" loop.
The foreach statement modifier is described well above that, with
"(with $_ aliased to each item in turn)." but no statement at that
point about localization.
The perlfunc docs for map and grep refer to "locally setting $_ to
each element", so I presume that means localizing in the same sense.
Testing shows that they are all indeed localized in the same way:
#! /usr/bin/perl
use strict;
use warnings;
my @names = (' in a loop: wilma', ' barney', ' bambam');
$_ = "\nfred\n";
print;
foreach (@names) { print }
print;
print foreach @names;
print;
map { print } @names;
print;
print grep { 1 } @names;
print;
exit 0;
produces
$ perl local/test/045.pl
fred
in a loop: wilma barney bambam
fred
in a loop: wilma barney bambam
fred
in a loop: wilma barney bambam
fred
in a loop: wilma barney bambam
fred
(That was in Perl 5.8.8, but that's not the sort of thing Perl tends
to change, for fear of breaking code.) (I've never before used
"print" with no arguments, implicitly printing $_. It feels weird.)
But "man perlop" says (in 5.8.8)
Ordinarily you must assign the returned value to a variable, but
there is one situation where an automatic assignment happens. If
and only if the input symbol is the only thing inside the
conditional of a "while" statement (even if disguised as a
"for(;

" loop), the value is automatically assigned to the global
variable $_, destroying whatever was there previously. (This may
seem like an odd thing to you, but you'll use the construct in
almost every Perl script you write.) The $_ variable is not
implicitly localized. You'll have to put a "local $_;" before the
loop if you want that to happen.
(BTW: "while <>" as a statement modifier works the same way as "while
(<>)" as a loop. I wasn't sure.)
Are there other cases of setting $_ implicitly? I can't think of any.
The while(<>) is an illustration of a silent bug.
And I don't know that "local $_" should be slow, given that every map,
grep, and foreach() has to do it.
I wouldn't ever use $_ as an ordinary variable, even in the main
program, except for oneliners with -n or -p.
If nothing else, it's not a descriptive variable name.