Packages

Chapter 2 - Perl Module Basics
by?Sam Tregar?
Apress ? 2002
has companion web siteCompanion Web Site

Perl supports modular programming through packages. Packages provide a separate namespace for variables and subroutines declared inside. This means that two packages can have subroutines and variables with the same names without inadvertently stepping on each other's toes. You declare a package with a package statement:

 package CGI::SimplerThanThou; 

After that, any subroutines or global variables you declare will be in the package. For example, this code creates a subroutine param() in the CGI::SimplerThanThou package:

 package CGI::SimplerThanThou; sub param {    return ('fake', 'params'); } 

Now if you want to call this subroutine from some other package, you'll need to prefix it with the package name:

 my @params = CGI::SimplerThanThou::param(); 

Variables can also be created in a package. Here's an example that creates a hash called %params in the CGI::SimplerThanThou package:

 package CGI::SimplerThanThou; %params = ( ten => 10 ); 

To refer to this variable from another package, you again use the package prefix:

 print "Ten: $CGI::SimplerThanThou::params{ten}\n"; 

Packages may not seem immediately useful, but they form the basis for modular programming in Perl by providing encapsulation. Since each package forms a separate namespace for variables and subroutines, a package is free to implement its functionality without concern for the rest of the program. For example, let's say I'd like to override Perl's logarithmic function, log(),[3] inside my package Acme::PotatoPeeler:

 package Acme::PotatoPeeler; sub log {    print STDERR "PotatoPeeler Says: $_[0]\n"; } 

If packages didn't provide encapsulation, I would have just overridden the logarithm function for the entire program, and the stock simulation algorithms in Acme::StockPicker wouldn't work so well! Of course, if that's what you really want, you can do that too. I'll explain how to use packages to "redefine the world" later.

Symbol Tables

Packages work through the magic of symbol tables. Each package has a hash associated with it called a symbol table. For every symbol in the package, there is a key in the hash. The value stored in the hash is a typeglob[4] containing the value for the symbol.

Why doesn't the hash directly store the value of the variable? Perl supports, for better or worse, variables of different types with the same name—you can have a scalar named $foo, an array named @foo, and a hash named %foo in the same package. The typeglob provides the level of indirection necessary to make this work.

Most compilers for other languages use symbol tables to keep track of variables declared in a program. Perl is unique in that it exposes its symbol tables to the programmer for examination and even manipulation at runtime. You can refer to a symbol table hash by using the package name plus a trailing package specifier, :: (double colon). Here's an example that prints out a sorted list of symbols for the File::Find package:

 use File::Find; print "$_\n" for sort keys %File::Find::; 

The list includes all the subroutines and variables defined in the package. It also includes the symbol tables for any packages that begin with File::Find. For example, if you were to also use the fictitious package File::Find::Faster, then the preceding code would list "Faster::" for File::Find::Faster's symbol table.

All nonlexical[5] symbols are stored in a symbol table—even global variables. What is normally referred to as a global variable in Perl is actually just a variable in the default package called "main::". You can access the main package's symbol table through two names—%main:: and %::. So, in actuality, Perl has no global variables— just package variables in the default package.

Aside from this default package, no automatic prefix is assumed. This means that all package names must be spelled out fully and are not based on the current package. For example, this code:

 package Poets::Appolinaire; @Books = qw(Alcools Calligrams); 

is not equivalent to:

 package Poets; @Appolinaire::Books = qw(Alcools Calligrams); 

In order to reference @Poets::Appolinaire::Books from within the Poets package, the full package name is required:

 package Poets; @Poets::Appolinaire::Books = qw(Alcools Calligrams); 

This is a good reason to keep your package names reasonably short—you'll have to type the full name whenever you need to refer to the package.

Caution 

Modules with similar names do not necessarily have any relationship. For example, the CGI and CGI::Thin modules have nothing in common. CGI::Thin is not necessarily a subclass of CGI, as those with object-oriented experience might think. The most you can say with confidence is that they both have something to do with CGI.

[3]Didn't know you could do that? I'll explain in more depth later in the "Exporting" section.

[4]There isn't room here to dip into the arcane world of typeglobs. Suffice it to say that, outside of some useful idioms that I'll cover later, you can use them to do some really odd things that are probably best left undone.

[5]Lexical symbols are those created with the my operator.



Writing Perl Modules for CPAN
Writing Perl Modules for CPAN
ISBN: 159059018X
EAN: 2147483647
Year: 2002
Pages: 110
Authors: Sam Tregar

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net