(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 strict
so 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
local
keyword, 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’slocal
is deprecated. It’s not. It’s just abused and misunderstood. - Lexical Scope –
my
andour
modify 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 betweenmy
andour
is thatmy
declarations disappear completely when the block is done, butour
declarations 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 ofour
that 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 strict
environment, 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
my
andour
are good throughout the entire block in which they were declared.our
identifiers however are also associated with a package, and you can get back to the same entity in a different scope by usingour
again. - Lexical variables can be “closed” as in the last
sub a
above. 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$foo
even after the scope in which that$foo
was 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!