Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Variable Scoping in Perl: the basics

by arturo (Vicar)
on Mar 23, 2001 at 21:39 UTC ( #66677=perltutorial: print w/ replies, xml ) Need Help??

Scoping

One thing you need to know to master Perl is how to deal with the scoping mechanisms it provides you with. You want globals? You got 'em! You want to avoid "collisions" (two variables with the same name clobbering each other)? You got it, and there's more than one way to manage the trick. But Perl's scoping rules aren't always so well understood, and it's not just the difference between my and local that trips people up, although clearing that up is going to be one of my purposes.

I've learned a lot from Coping with Scoping and sections in various Perl books ( e.g.Effective Perl Programming ). So credit has to go to those authors (Dominus for the first, and Joseph N. Hall and merlyn for the second. Dominus also provided some helpful corrections to errors (some egregious) to an earlier version of this tutorial, so he should get at least second-author credit. However, the documentation that comes with your local perl installation is always the most up-to-date you can get, so don't be afraid to use perldoc perlop and perldoc -f foo</code>! on your own system.

Summary

Yes, at the beginning ...

  • my provides lexical scoping; a variable declared with my is visible only within the block in which it is declared.
  • Blocks of code are hunks within curly braces {}; files are blocks.
  • Use use vars qw([list of var names]) or our ([var_names]) to create package globals.
  • local saves away the value of a package global and substitutes a new value for all code within and called from the block in which the local declaration is made.

Namespaces

A basic idea, although one you need not master to write many scripts, is the notion of a namespace. Global variables (variables not declared with my live in a package. A package provides a namespace, which I'm going to explain by reference to the metaphor of a family name. In English speaking countries, "Robert" is a reasonably common name, so you (assuming you live in one) probably know more than one "Robert." Usually, for us humans, the current conversational context is enough to determine for our audience which Robert we're talking about (my chums down at the pool hall know Robert the darts genius, but at work, "Robert" is the CEO of our failing dot-com).

Of course these people have family names too (yes, those can be shared by different people as well -- but you can't expect this metaphor to be perfect =), and if we wanted to be fully explicit we'd add that to allow our audience to determine which Robert we are talking about. $Smith::Robert is a creature distinct from $Jones::Robert. When you have two different variables with the same (as it were) 'first name', you can explicitly declare which one you want to refer to, no matter where you are in your code, by using the full name of the variable.

Use the package operator to set the current package. When you put package Smith in your code, you are, in effect, saying that every unqualified variable or function name should be understood to belong to the Smith package. To go with our metaphor, you're saying "in this bit of code, I want to talk about the Smith family."

Implicitly, there's a package main; at the top of your scripts; that is, unless you explicitly declare a different package, all the variables you declare (keeping the caveat about my in mind) will be in main. Variables that live in a package are reasonably called "package globals", because they are accessible by default to every operator and subroutine that lives in the same package (and, if you're explicit about their names, outside the package, too).

Using packages makes accessing Perl variables sort of like travelling in different circles. For example, at work, it's understood that "Robert" is "Robert Szywiecki", the boss. At the pool hall, it's understood that "Robert" is "Robert Yamauchi", the darts expert. Here's a little code to illustrate the use of packages:

#!/usr/bin/perl -w package Szywiecki; $Robert = "the boss"; sub terminate { my $name = shift; # the following line was updated on 2004-12-29 following on aristotl +e73's comment print "$Robert has canned ${name}'s sorry butt\n"; } terminate("arturo"); # prints "the boss has canned arturo's sorry butt +" package main; # terminate("arturo"); # produces an error if you uncomment it

The variable $Robert's full name, as it were, is $Szywiecki::Robert (note how the $ moves out to the front of the package name, indicating that this is the scalar Robert that lives in package Szywiecki). To code and, most importantly, subroutines in the Szywiecki package, an unqualified $Robert refers to $Szywiecki::Robert -- unless $Robert has been 'masked' by my or local (more on that later).

Now, if you use strict (and you should, you should, you should -- see strict.pm, for example), you'll need to declare those global variables before you can use them, UNLESS you want to fully qualify them. That's why the second (apparent) call to terminate in the above example will fail. It's expecting to find a subroutine terminate in the main package, but no such critter has been defined. That is,

#!/usr/bin/perl -w use strict; $Robert = "the boss"; # error! print "\$Robert = $Robert\n";

will produce an error, whereas if we fully qualified the name (remember that implicit package main in there), there's no problem:

#!/usr/bin/perl -w use strict; $main::Robert = "the boss"; print "\$main::Robert = $main::Robert\n";

To satisfy strict 'vars' (the part of strict that enforces variable declaration), you have two options; they produce different results, and one is only available in perl 5.6.0 and later:

  1. our ($foo, $bar) operator (in perl 5.6.0 and above) declares $foo to be a variable in the current package.
  2. use vars qw($foo $bar) (previous versions, but still works in 5.6) tells 'strict vars' that these variables are OK to use without qualification in the current package.

One difference between our and and the 'older' use vars is that our provides lexical scoping (more on which in the section on my below).

Another difference is that with use vars, you are expected to give an array of variable names, not the variables themselves (as with our). Both mechanisms allow you to use globals while still maintaining one of the chief benefits of strict 'vars': you are protected from accidently generating a new variable via a typo. strict 'vars' demands that your variables be explicitly declared (as in "here's a list of my package globals"). Both of these mechanisms allow you to do this with package globals.

A thing to remember about packages (and potentially a bad thing, depending on how big a fan you are of "privacy") is that package globals aren't just global to that package, but they can be accessed from anywhere in your code, as long as the names are fully qualified. You can talk about Robert the darts expert at work, if you say "Robert Yamauchi" (warning: I didn't use strict here, but it's only for purposes of brevity!):

#!/usr/bin/perl -w package Szyewicki; $Robert = "the boss"; package PoolHall; $Robert = "the darts expert"; package Sywiecki; # back to work! print "Here at work, 'Robert' is $Robert, but over at the pool hall, ' +Robert' is $PoolHall::Robert\n";

See? Understanding packages isn't really all that hard. Generally, a package is like a family of variables (and subroutines! the full name of that terminate in the example above is &Szywiecki::terminate -- similar remarks apply to hashes and arrays, of course).

my (and a little more on our) a.k.a. lexical scoping

Variables declared with my are not globals, although they can act sort of like them. A main use of my is to operate on a variable that's only of use within a loop or subroutine, but that's by no means where it ends. Here are some basic points about my

  • A my variable has a block of code as its scope (i.e. the places in which it is accessible).
  • A block is often declared with braces {}, but as far as Perl is concerned, a file is a block.
  • A variable declared with my does not belong to any package, it 'belongs' only to its block
  • Although you can name blocks (e.g. BEGIN, with which you may already be familiar), you can't fully qualify the name of the block to get to the my variable.
  • File-level my variables are those which are declared in a file outside of any block within that file.
  • You can't access a file-level my variable from outside of the file in which it is declared (unless you explicitly return it from a subroutine, for example).

As long as you're writing one-file scripts (e.g. ones that don't import modules), some of these points don't matter a great deal. But if you're heavily into "privacy" and "encapsulation", and if you write modules and OO modules you will be, you'll need to understand all of the above.

Here's some commented code to explain some of these points:

#!/usr/bin/perl -w use strict; #remember we're in package main use vars qw($foo); $foo = "Yo!"; # sets $main::foo print "\$foo: $foo\n"; # prints "Yo!" my $foo = "Hey!"; # this is a file-level my variable! print "\$foo: $foo\n"; # prints "Hey!" -- new declaration 'masks' the +old one { # start a block my $foo = "Yacht-Z"; print "\$foo: $foo\n"; # prints "Yacht-Z" -- we have a new $foo in scope. print "\$main::foo: $main::foo\n"; # we can still 'see' $main::foo subroutine(); } # end that block print "\$foo: $foo\n"; # there it is, our file-level $foo is visible a +gain! print "\$main::foo: $main::foo\n"; # whew! $main::foo is still there! sub subroutine { print "\$foo: $foo\n"; # prints "Hey!" -- as the script is written # why? Because the variable declared in the naked block # is no longer in scope -- we have a new set of braces. # but the file-level variable is still in scope, and # still 'masks' the declaration of $main::foo } package Bar; print "\$foo: $foo\n"; # prints "Hey!" -- the my variable's still in s +cope # if we hadn't made that declaration above, this would be an error: th +e # interpreter would tell us that Bar::foo has not been defined.

As the bottom bit in the above example shows, because they don't live in any package, my variables can be visible even though a new package has been declared because the block is the file (at least for these purposes)

Now the example above used a 'naked' block -- there's no control structure (e.g. if or while) involved. But of course that makes no difference to the scoping.

File-level my variables ARE accessible from within blocks defined within that file (as the example above shows) this is one way in which they're sort of like globals. If, however, subroutine had been defined in a different file, we would have a run-time error. Once you know how my works, you can see, just by looking at the syntax of the file, where a my variable is going to be accessible. This is one reason the scoping it provides is called "lexical scoping." Here's a place where use vars and the 'new' our operator differ: if you specify our $foo in package Bar but outside of an explicit block, you're in effect saying that (until some other scoping operator comes into play) occurrences of $foo are to be understood as referring to $Bar::foo. This should illustrate the difference between use vars and the newer our:

#~/usr/bin/perl -w use strict; our ($bob); use vars qw($carol); $carol = "ted"; $bob = "alice"; print "Bob => $bob, Carol => $carol\n"; package Movie; print "Bob => $bob, Carol => $carol\n";

Note that having the second print will produce an error, because $carol is interpreted as $Movie::carol, while $bob is interpreted as $main::bob.

While this "package spanning" (which is only apparent in the case of our!) is a partial functional similarity between the two different kinds of lexical scoping operators, don't forget the difference, which is that our declares a package global, while my does not.

local -- a.k.a. dynamic scoping

Now we arrive at local, which is only sort of like my, but due to its name, its function is sometimes confused with that of my. Here's the skinny : local $foo saves away the current value of the (package) global $foo, and determines that in the current block and any code called by the current block, $foo refers to whatever value you give it in that block (a bare local $foo will set $foo to undef; the same goes for my). As things now stand, local only works on globals, you can't use it on a my variable.

Since local can affect what happens outside of the block in which it's used, local provides what's called dynamic scoping, as its effect is determined by what happens when the script is run. That is, the compiler can't tell when local is going to have its effect or not at the time it's compiling the script (which happens before the script is run). This distinguishes dynamic scoping from the lexical scoping provided by my and our, the effects of which can be checked at compile time.

The basic upshot of this difference is that if you localize a variable within a block and call a subroutine from that block, that subroutine will see the value of the localized variable. This is a major difference between my and local. Compare the above example to this one:

#!/usr/bin/perl -w use strict; use vars qw ($foo); # or "our $foo" if you're using 5.6 $foo = "global value"; print "\$foo: $foo\n"; # prints "global value" print "mysub result '", &mysub(), "'\n"; #"global value" print "localsub result '", &localsub(), "'\n"; # "local value" print "no sub result '",&showfoo(), "'\n"; #"global value" sub mysub { my $foo = "my value"; showfoo(); # } sub localsub { local $foo = "local value"; showfoo(); # ALWAYS prints "local value" } sub showfoo { return $foo; }
original example modified as per Masem's note. Thanks!

Notice that the my declaration in mysub gets (apparently) ignored by showfoo (since we've left the block in which the my declaration is valid, but the local declaration in localsub doesn't get ignored. But after we've left that block, the original value of $foo is visible again.

I hope you learn as much from reading this as I did from writing it!

Comment on Variable Scoping in Perl: the basics
Select or Download Code
Re: Variable Scoping in Perl: the basics
by Masem (Monsignor) on Mar 23, 2001 at 22:58 UTC
    Excellent review of scoping, arturo. The only nit that I have with the writeup is that you leave some of the more important results of print results out (for example, in the very last example, what does the last print statement in the main body of the problem put out?). Certainly, one can copy and paste the code into perl and see what comes out, bu it might be better to make sure to include the unmodified output for each little script right after the script, making sure that each printed line can be unambigously traced back into the program.

    But kudos on covering a difficult subject and getting across the difference between my and local, something I've always had trouble with!

    Update: Arturo did the corrections as indicated, so this is most redundant, but this comment should still serve to remind future writers to include all output particularly if it's necessary for program understading :).


    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re: Variable Scoping in Perl: the basics
by Dominus (Parson) on Mar 23, 2001 at 23:35 UTC

      Thanks for noticing that (did you get a few 404's =), and of course for writing it in the first place!

      It is now fully fixed.

      Philosophy can be made out of anything. Or less -- Jerry A. Fodor

        Says arturo:
        Thanks for noticing that
        Welcome.
        Dominus also provided some helpful corrections to errors, so he should get at least second-author credit.
        I don't agree. I only made two small corrections. Author credit would be inappropriate.

        Thanks, though.

Re: Variable Scoping in Perl: the basics
by thecap (Initiate) on Nov 11, 2004 at 03:00 UTC
    I have two files:
    # inc.pl use vars qw($foo); $foo = "hello"; 1;
    # t.pl use strict; use vars qw($foo); do 'inc.pl'; print $foo, "\n";
    If I remove the 'use vars' from t.pl than t.pl fails to run with the error 'Global symbol "$foo" requires explicit package name'. How can I create a main:: global variable in inc.pl which I can access from t.pl without explicitly listing it in a 'use vars'?

    I would like to have lots of variables in inc.pl without listing each of them in files that use them.

    Thank you for any help.

      The text of the tutorial doesn't mention the fact that the scope of the effect of use vars is file-level. This is, however, documented in the perldoc for vars:

      the "use vars" and "use subs" declarations are not BLOCK-scoped. They are thus effective for the entire file in which they appear.
      (it's also mentioned under "Pragmatic Modules" in the perlmodlib man page).

      Even though its "maximum reach" is one file, the effects of use vars are still different than those of our, which was all I was trying to document in the tutorial.

      So, the general answer to your question is that you can't do exactly what you say you want to do, and that's one of the points of use strict: if you're going to use a variable in a file, you have to declare it explicitly in that file; it encourages you to know where everything's coming from, and protects you from typos in variable names.

      This doesn't mean your problem's insoluble, though. If, you want inc.pl to serve the function of being a "configuration script" that initializes a bunch of values so other scripts can use them, you can have it work this way: create one data structure (say, a hash), and 'export' that hash. This way, a script that uses inc.pl will only need to declare one variable with our or use vars; of course, with a hash, you lose the safety mentioned as one of the chief benefits of use strict.

      For this reason, instead of using a simple hash, you might want to have inc.pl be an object oriented module, but that's beyond the scope of this tutorial.

      HTH!

      If not P, what? Q maybe?
      "Sidney Morgenbesser"

Re: Variable Scoping in Perl: the basics
by aristotle73 (Sexton) on Dec 20, 2004 at 19:09 UTC
    print "$Robert has canned $name's sorry butt\n"; I tried running this in PERL and it yelled at me saying that it didn't like $name::s. I changed this line of code to: print "$Robert has canned $name sorry butt\n"; And it worked fine 0_o An error in the tutorial perhaps?

      Try

      print "$Robert has canned ${name}'s sorry butt\n";

      The apostrophe is the old-style package separator, still supported, so $name's is indeed equivalent to $name::s. By putting the curlies in there, you tell Perl exactly which part of the string to consider part of the variable name, and which part to consider a literal value.

      Makeshifts last the longest.

        Thanks :D It works ^_^
Re: Variable Scoping in Perl: the basics
by Ultra (Hermit) on Feb 19, 2005 at 14:36 UTC
    Hello. I'd like to translate this article and put it on a Romanian Site http://perlromania.net
    Can I do this? Of course, by mentioning the original author and the link where one can find the article.
    Thanks.
    Dodge This!
Re: Variable Scoping in Perl: the basics
by planetscape (Canon) on Jul 04, 2006 at 14:07 UTC
Re: Variable Scoping in Perl: the basics
by Anonymous Monk on Mar 23, 2007 at 05:48 UTC
    Simply fabulous explanation on scoping.
Re: Variable Scoping in Perl: the basics
by thinairtraveler (Initiate) on Apr 29, 2008 at 21:13 UTC
    Years after the article, this was highly useful for someone new to Perl. Thanks.
Re: Variable Scoping in Perl: the basics
by nagalenoj (Friar) on Jan 24, 2009 at 06:43 UTC
    Nice page to read about variable scoping. It gives a clear picture about the scope. Clear definitions and examples.
Re: Variable Scoping in Perl: the basics
by CarlChe (Initiate) on Jan 01, 2014 at 00:25 UTC
    Thanks very much, very helpful...

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perltutorial [id://66677]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (12)
As of 2014-10-31 13:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (217 votes), past polls