Do you see why? This is an especially bad variant on the common while-loop inside for smashing aliased $_ problem, which usually elicits a couple of points:use strict; use warnings; use File::Spec::Functions "devnull"; sub bar { open my $fh, "< $_[0]" or die "couldn't open $_[0]: $!"; print while <$fh>; } sub foo { for (@_) { bar(devnull()) } } $. = 0; foo($.);
Here, I am calling foo("true", "the following statement is true"); and foo("false", "the following statement is false");, but by the time foo gets to line 12, $tf is not set to the passed parameter. The container $1 was passed, and before it was assigned to $tf, an intervening regex undefined it. (However, because $1 is dynamically scoped, once foo() returns, $1 will again be "true" or "false".)use strict; use warnings; use Data::Dumper; $Data::Dumper::Terse=1; sub foo { print "foo: bad args: ", Dumper \@_ if @_ != 2 || $_[0] !~ /^[tf]/ || $_[1] !~ /statement/; my ($tf, $statement) = @_; if ($tf =~ /^t/) { # Line 12 print "true: $statement\n"; } else { print "false: $statement\n" } } for my $statement ("the following statement is true", "the preceding statement is false") { $statement =~ /\b(t|f|true|false)\b/ or next; foo($1, $statement); }
The moral here is to beware action at a distance; when passing magic variables, or even your own globals, if you want them passed by value, explicitly stringify or numify them:
so that the callee gets the value at the time of the call.foo(0+$.); # and foo("$1", $statement);
In reply to Passing globals and magic variables safely by ysth
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |