(initially published 2012-05-16)
I have a love-hate relationship with Perl’s scoping model. It has quite obviously grown over time so it is kind of twisted and knotted like a tree. However, all those twists and knots make it easy to climb if you know what you’re doing. So lets review the different types of scope:
- Package Scope – Package scope is actually really just global scope with the caveat that unqualified identifiers refer to the current package setting. This is the default scope, though naked package-scoped variables are fraught with peril, so I will repeat the admonition to
use strictso you don’t end up hanging yourself from the Perl tree with a noose made of your own code. Subroutine declarations (at least “nonymous” ones) are almost always package/globally scoped. Perl’s magic variables (such as$_) are generally package-scoped as well. - Dynamic Scope – Using the
localkeyword, we can restrict the declarations of variables, typeglobs, etc. to only be valid within the confines of our current block and everything we call from within that block. The declarations essentially have global/package scope until we exit the current block. This means we can override global declarations for the duration of the block, or we can materialize our own pseudo-global subroutines and make them disappear just as quickly when we’re done with them. People try to tell me Perl’slocalis deprecated. It’s not. It’s just abused and misunderstood. - Lexical Scope –
myandourmodify declarations so that they are only meaningful within the block within which the declaration occurs. This includes sub-blocks, but it does not include calls to code that is defined outside of the lexical block. The primary distinction betweenmyandouris thatmydeclarations disappear completely when the block is done, butourdeclarations can be re-accessed in an entirely different scope (or the next time we re-enter this scope) by another use ofour. This creates “hidden” global variables that can be explicitly revealed within any given lexical scope. There are more peculiarities ofourthat the Perl docs can certainly elucidate more than I have patience to.
Here’s some examples that hopefully will make some of the differences clear:
$foo = 0; # AKA $main::foo
sub a { print "$foo\n"; }
a(); # prints "0"
package bar;
$foo = 1; # AKA $bar::foo
main::a(); # still prints "0"
sub a { print "$foo\n"; }
a(); # prints "1"
{
local $foo = 2;
a(); # prints "2"
local $main::foo = 3;
main::a(); # prints "3"
}
a(); # prints "1" again
main::a(); # prints "0" again
my $foo = 4; # lexically scoped, not the same as $bar::foo
a(); # prints "1"
package baz;
print "$foo\n"; # prints "4"
{
my $foo = 5;
sub a {
print "$foo\n";
}
a(); # prints "5"
}
print "$foo\n"; # prints "4" again
a(); # prints "5" again. Aha! A closure!
{
our $foo = 6;
package moo;
print "$foo\n"; # still prints "6" b/c "our" is lexical
our $foo = 7; # Lexical but associated with the moo package
}
{
package moo;
print "$foo\n"; # prints "4" still
}
{
our $foo;
print "$foo\n"; # prints "6"
package moo;
our $foo;
print "$foo\n"; # prints "7"
}
- Please note, the above won’t work in a
use strictenvironment, because of the use of unqualified global variables. It’s a little like driving without a seatbelt. You really can if you need to, but in almost all circumstances there’s just no need to take the risk. - Globals and locals are forever bound to a package scope. If you switch packages, the same names refer to entirely different entities.
- Lexical identifiers, declared with
myandourare good throughout the entire block in which they were declared.ouridentifiers however are also associated with a package, and you can get back to the same entity in a different scope by usingouragain. - Lexical variables can be “closed” as in the last
sub aabove. In this case, the subroutine is actually defined in the global package scope despite the enclosing anonymous block, and maintains a reference to the lexically defined$fooeven after the scope in which that$foowas originally defined is gone. We’ll get back to closures more in another post.
Now, you may ask yourself, why is any of this a good thing? This post is unfortunately short on some of the sexy techniques I have been advertising, but scoping is foundational to some truly mindblowing stunts which are soon to come. So study up. This will be on the final!