Schnee (schnee) wrote,


Argh, Perl... I love you, but sometimes you drive me nuts. Take this program:


use v5.10.0;

my @dir = ("foo");

sub process_dir {
	my ($dir) = @_;
	1 while(glob("${dir}/*"));

say "dir = $dir[0]";
process_dir($_) foreach (@dir);
say "dir = $dir[0]";

which produces this output:

$ perl
dir = foo
dir =

This had me puzzled for a good 20 minutes. As far as I can tell, the reason why this is happening is that both the while loop in process_dir and the foreach loop in the main program implicitely assign to $_; in the latter case, though, it's not actually assignment as much as aliasing... and there is only one $_ that's globally shared among all code.

Who'da thunk that $_ is global that way, though? Checking in Programming Perl (the older 3rd edition), this is briefly mentioned on page 658, but I don't think I ever ran into it in practice, and I'm finding it counterintuitive, too. $_ is supposed to be the "topic" that is currently being talked about, and the loops are unrelated, in different scopes, separated by a function call. They're obviously having different conversations, as it were, talking about different things.

At least it means that the problem's easily fixed. But really, doesn't this mean that it's basically unsafe to use $_ anywhere in subroutines given that you can never be sure the caller might not be using it for something already? Maybe I should ask about that on perlmonks or so.

EDIT: Well, you can localize it to be on the safe side, of course, but that's clunky and inelegant. I expect Perl to be DWIMmier than that.

Tags: perl, programming
  • Post a new comment


    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded