There are two ways of getting private values inside a subroutine or block. One is to use the local operator, which operates on global variables only; it saves their values and arranges to have them restored at the end of the block. The other option is to use my, which not only creates a new variable, it marks it as private to the block.
On the surface, both local and my behave identically:
$a = 20; # global variable
{
local ($a); # save $a's old value;
# new value is undef
my (@b); # Lexical variable
$a = 10; # Modify $a's new value
@b = ("wallace", "grommit");
print $a; # prints "10"
print "@b"; # prints "wallace grommit"
}
# Block ended. Back to global scope where only $a is valid
print $a; # prints "20", the old value
print @b; # prints a warning, because no global @bA global variable created because of a local statement gets deallocated at the end of the block.
While their usage is identical, there's one important difference between local and my. The my declaration creates truly local variables, such as auto variables in C. This is called lexical binding. The variable is private to the block in which it is declared and is available only to that block (what you can see lexically defines the bounds). It is not available to subroutines that are called from the block.
In contrast, the local operator does not create new variable. When applied to global variables, it squirrels their values away and restores them at the end of the block. Because the variables themselves are global, their new value is available not only to the block in which the local operator is used, but also to all called subroutines. Consider
$x = 10;
first();
sub first {
local ($x) = "zen"; # $x is still global, and has a new value
second();
}
sub second {
print $x; # Prints "zen", the current value of the global $x
}From global scope, we call first, which localizes the global $x, sets it to a new value (the string "zen"), and calls second. second sees the last value of $x, as set by first. This process is called dynamic scoping, because the value of $x seen by second depends on the particular call stack. This feature can be quite confusing in practice, because if you wrote another subroutine that declared a local $x and called second, it would pick up that version of $x.
In other words, local makes a global variable's new value temporary; it does not change the essential nature of the variable itself (it still remains global). my creates a truly local variable. Which is why you can say
local $x{foo}; # Squirrel away $x{foo}'s value.but not
my $x{foo}; # Error. $x{foo} is not a variableIt is recommended that you use my wherever possible, because you almost always want lexical scoping. In addition, as we shall see in Chapter 20, lexically scoped variables are faster than dynamically scoped variables.
The fact that local saves a variable's value and arranges to have that value restored at the end of the block results in a very neat idiom: localizing built-in variables. Consider a local version of the built-in array representing the program's arguments, @ARGV:
{ # Start of a new block
local(@ARGV) = ("/home/alone", "/vassily/kandinski");
while (<>) {
# Iterate through each file and process each line
print; # print, for example
}
} # Block ends. The original @ARGV restored after this.The diamond operator (<>) needs a globally defined @ARGV to work, so it looks at the typeglob corresponding to the ARGV entry in the symbol table.[] What it doesn't know, however, is that local has temporarily replaced @ARGV's value with a different array. The diamond operator treats each element of this array as a filename, opens it, reads a line in every iteration, and moves on to the first line of the next file when necessary. When the block is over, the original @ARGV is restored. This example does not work with my, because this operator creates a wholly new variable.
This technique works for other built-in variables too. Consider the variable $/ , which contains the input record separator ("\n" by default). The diamond input operator uses this separator to return the next chunk (by default, the next line). If you undef it, the whole file is slurped in, in one fell swoop. To avoid having to save the original value of $/ and restore it later, you can use local instead, like this:
{
local $/ = undef; # Saves previous value of $/, and substitutes
# it with undef
$a = <STDIN>; # Slurp all of STDIN into $a
}local is also used for localizing typeglobs, which, as it turns out, is the only way of getting local filehandles, formats, and directory handles.