Understanding Scope and Packages in Perl

In this fourth part of a six-part article series on subroutines and functions in Perl, you will learn about two different types of variables (global and lexical) and their scopes. You will also learn what a package is. This article was excerpted from chapter six of the book Beginning Perl, Second Edition, written by James Lee (Apress; ISBN: 159059391X).

Understanding Scope

It’s now time to have a look at what we’re doing when we declare a variable with my() . The truth, as we’ve briefly glimpsed it, is that Perl has two types of variable. One type is the global variable (or package variable), which can be accessed anywhere in the program, and the second type is the lexical variable (or local variable), which we declare with my() .

Global Variables

All variables in the program are global by default. Consider this code:

#!/usr/bin/perl -w

$x = 10;

$x is a global variable. It is available in every subroutine in the program. For instance, here is a program that accesses a global variable:

#!/usr/bin/perl -w
# global1.pl

$x = 10;


sub access_global {
print "value of $x: $xn";

Executing this code shows that $x is accessible in access_global() :

$ perl global1.pl
value of $x: 10

Since variables within functions are global by default, functions can modify variables as shown in this program:

#!/usr/bin/perl -w
# global2.pl

$x = 10;

print "before: $xn";
print "after: $xn";

sub change_global {
$x = 20;
print "in change_global(): $xn";

This program assigns the global variable $x the value 10 and then prints that value. Then, change_global() is invoked. It assigns $x the value 20—this accesses the global variable $x —and then prints its value. Then in the main part of the code, after the function is called, the global $x is printed with its new value—20. Here we see the proof:

$ perl global2.pl
before: 10
in change_global(): 20
after: 20

The fact that Perl function variables are global by default is itself not a bad thing, unless of course you are not expecting it. If you are not expecting it, then accidentally overwriting global variables can cause hard-to-find bugs. If you are expecting it, you will probably want to make function arguments local.

{mospagebreak title=Introduction to Packages}

When we start programming, we’re in a package called main . A package is a collection of vari ables that is separate from another package. Let’s say we have two packages: A and B. Each package can have its own variable named $x , and those two $x variables are completely distinct.

If we assign $x , as we did previously in global2.pl , then we create a package variable $x in package main (the main package is the default package). Perl knows it by its full name, $main::x —the variable $x in the main package—but because we’re in the main package when we make the assignment, we can just call it by its short name, $x . It’s like the phone system— you don’t have to dial the area code when you call someone in the same area as you.1

1. Depending on your location, of course. Nowadays, with so many area codes in a metropolitan area, to call across the street often requires dialing 10 digits . . .

We can create a variable in another package by using a fully qualified name. Instead of the main package, we can have a package called Fred . Here we’ll store all of Fred’s variables and subroutines. So, to get at the $name variable in package Fred , we say $Fred::name , like this:

$x = 10 ;
$Fred::name = "Fred Flintstone";

The fact that it’s in a different package doesn’t mean we can’t get at it. Remember that these are global variables, available from anywhere in our program. All packages do is give us a way of subdividing the namespace.

What do we mean by “subdividing the namespace”? Well, the namespace is the set of names we can give our variables. Without packages, we could only have one $name . What packages do is help us make $name in package Fred different to $name in package Barney and $name in package main .

#!/usr/bin/perl -w
# globals1.pl

$main::name = "Your Name Here"; $Fred::name = "Fred Flintstone"; $Barney::name = "Barney Rubble";

print "$name in package main is $namen"; print "$name in package Fred is $Fred::namen";
print "$name in package Barney is $Barney::namen";

$ perl globals1.pl
$name in package main is Your Name Here $name in package Fred is Fred Flintstone $name in package Barney is Barney Rubble

You can change what package you’re currently working in with the aptly named package operator. We could write the preceding like this:

#!/usr/bin/perl -w
# globals2.pl

$main::name = "Your Name Here";
$Fred::name = "Fred Flintstone"; $Barney::name = "Barney Rubble";

print "$name in package main is $namen";
package Fred;
print "$name in package Fred is $namen";
package Barney;
print "$name in package Barney is $namen";
package main;

When use strict is in force, it makes us use the full names for our package variables. If we try and say this:

#!/usr/bin/perl -w
# strict1.pl

use strict;

$x = 10;
print $x;

Perl will give us an error—global symbol $x requires an explicit package name. The package name it’s looking for is main , and it wants us to say $main::x .

#!/usr/bin/perl -w
# strict2.pl

use strict;

$main::x = 10;
print $main::x, "n";

Global variables can be accessed and altered at any time by any subroutine or assignment that you care to apply to them. Of course, this is handy if you want to store a value—for instance, the user’s name—and be able to get it anywhere.

It’s also an absolute pain in the neck when it comes to subroutines. Here’s why:

$a = 25;
$b = some_sub(10);
print $a;

Looks innocent, doesn’t it? Looks like we should see the answer 25. But what happens if some_sub() uses and changes the global $a ? Any variable anywhere in your program can be wiped out by another part of your program—we call this action at a distance, and it gets real spooky to debug. Packages alleviate the problem, but to make sure that we never get into this mess, we have to ensure that every variable in our program has a different name. In small programs, that’s feasible, but in huge team efforts, it’s a nightmare. It’s far clearer to be able to restrict the possible effect of a variable to a certain area of code, and that’s exactly what lexical variables do.

[gp-comments width="770" linklove="off" ]

chat sex hikayeleri Ensest hikaye