local EXPR
This operator declares one or more global variables to have locally scoped values within the innermost enclosing block, subroutine, eval, or file. If more than one variable is listed, the list must be placed in parentheses, because the operator binds more tightly than comma. All the listed variables must be legal lvalues, that is, something you could assign to. This operator works by saving the current values of those variables on a hidden stack and restoring them upon exiting the block, subroutine, or eval, or file. After the local is executed, but before the scope is exited, any called subroutines will see the local, inner value, not the previous, outer value, because the variable is still a global variable, despite having a localized value. The technical term for this is "dynamic scoping".
The EXPR
may be assigned to if desired, which allows you to initialize
your local variables. (If no initializer is given, all scalars are
initialized to the undefined value and all arrays and hashes
to empty.) Commonly, this is used to name the
formal arguments to a subroutine. As with ordinary assignment, if you
use parentheses around the variables on the left (or if the variable is
an array or hash), the expression on
the right is evaluated in list context. Otherwise the expression
on the right is evaluated in scalar context.
Here is a routine that executes some random piece of code that depends
on $i
running through a range of numbers. Note that the scope
of $i
propagates into the eval code.
&RANGEVAL(20, 30, '$foo[$i] = $i'); sub RANGEVAL { local($min, $max, $thunk) = @_; local $result = ""; local $i; # Presumably $thunk makes reference to $i for ($i = $min; $i < $max; $i++) { $result .= eval $thunk; } $result; }
This code demonstrates how to make a temporary modification to a global array:
if ($sw eq '-v') { # init local array with global array local @ARGV = @ARGV; unshift @ARGV, 'echo'; system @ARGV; } # @ARGV restored
You can also temporarily modify hashes:
# temporarily add a couple of entries to the %digits hash if ($base12) { # (NOTE: not claiming this is efficient!) local(%digits) = (%digits, T => 10, E => 11); parse_num(); }
But you probably want to be using my instead, because local isn't really what most people think of as local. See the section on my later.