I have the following method which accepts a variable and then displays info from a database:
sub showResult {
if (@_ == 2) {
my @results = dbGetResults($_[0]);
if (@results) {
foreach (@results) {
print "$count - $_[1] (ID: $_[0])\n";
}
} else {
print "\n\nNo results found";
}
}
}
Everything works fine, except the print line in the foreach loop. This $_ variable still contains the values passed to the method.
Is there anyway to 'force' the new scope of values on $_, or will it always contain the original values?
If there are any good tutorials that explain how the scope of $_ works, that would also be cool!
Thanks
In Perl, the _
name can refer to a number of different variables:
The common ones are:
$_ the default scalar (set by foreach, map, grep)
@_ the default array (set by calling a subroutine)
The less common:
%_ the default hash (not used by anything by default)
_ the default file handle (used by file test operators)
&_ an unused subroutine name
*_ the glob containing all of the above names
Each of these variables can be used independently of the others. In fact, the only way that they are related is that they are all contained within the *_
glob.
Since the sigils vary with arrays and hashes, when accessing an element, you use the bracket characters to determine which variable you are accessing:
$_[0] # element of @_
$_{...} # element of %_
$$_[0] # first element of the array reference stored in $_
$_->[0] # same
The for
/foreach
loop can accept a variable name to use rather than $_
, and that might be clearer in your situation:
for my $result (@results) {...}
In general, if your code is longer than a few lines, or nested, you should name the variables rather than relying on the default ones.
Since your question was related more to variable names than scope, I have not discussed the actual scope surrounding the foreach loop, but in general, the following code is equivalent to what you have.
for (my $i = 0; $i < $#results; $i++) {
local *_ = \$results[$i];
...
}
The line local *_ = \$results[$i]
installs the $i
th element of @results
into the scalar slot of the *_
glob, aka $_
. At this point $_
contains an alias of the array element. The localization will unwind at the end of the loop. local
creates a dynamic scope, so any subroutines called from within the loop will see the new value of $_
unless they also localize it. There is much more detail available about these concepts, but I think they are outside the scope of your question.