6. Modules
Contents:
Life is a struggle with things to maintain itself among them. Concepts are the strategic plan we form in answer to the attack. - Jose Ortega y Gasset, The Revolt of the Masses One of the chief reasons why languages such as awk and the various Unix shells don't get used for building even moderately complex systems is their lack of support for modular programming. There are no bodies of code that you can just pick up and plug into your application; instead, you end up cutting and pasting from other standalone scripts. In contrast, languages such as Perl have been highly successful because of the wide availability of third-party modules (libraries). When comparing languages, I consider the availability of libraries to be more important than pure language features. Perl allows you to partition your code into one or more reusable modules. In this chapter, we will study how to:
6.1 Basic PackageThe package keyword signifies the beginning of a new namespace. All global identifiers (names of variables, subroutines, filehandles, formats, and directory handles) mentioned after this statement "belong" to that package. For example: package BankAccount ; $total = 0; sub deposit { my ($amount)= @_; $total += $amount; print "You now have $total dollars \n"; } sub withdraw { my ($amount)= @_; $total -= $amount; $total = 0 if $total < 0; print "You now have $total dollars \n"; } The user-defined global identifiers $total , deposit , and withdraw belong to the BankAccount package. The scope of a package lasts until the end of the innermost enclosing block (if it is declared inside that block) or until another package statement is encountered. In the absence of an explicit package declaration, Perl assumes a package name called main . This is how you use the global symbols from another package: package ATM; # Start a different name-space now BankAccount::deposit(10); # Call a foreign subroutine print $BankAccount::total; # Access a foreign variable
To access an identifier in a different
namespace, you need to put the package name before the variable name; this is called
fully qualifying
the name. Note that you must say
$BankAccount::total
, not
BankAccount::$total
; the Since the package statement simply dictates the effective namespace, you can switch between different namespaces at will: package A ; $a = 10; # This $a is in package A package B; $a = 20; # This $a is in package B, and is completely independent # of the other $a package A ; # Make A the current package. print $a; # prints 10; C++ programmers will recognize the resemblance to that language's namespace facility. 6.1.1 Packages and Variables
In
Chapter 3,
Typeglobs and Symbol Tables
, I mentioned that all global names go into a symbol table. That was a bit of a white lie. Each package actually gets its
own
symbol table, distinct from all others. (We will have more to say on this subject in the section
"Accessing the Symbol Table
" later in this chapter). User-defined identifiers in package
main
are not treated specially in any way except that you can also refer to a variable, say
$x
, in that package as The built-in variables such as $| , $_ , @ARGV , and %ENV always belong to package main , and Perl allows you to refer to these variables in any package without having to prefix them with main:: . These are the only truly global variables in Perl. You may also recall that lexical ( my ) variables are not associated with symbols and typeglobs and therefore have nothing to do with packages. It is a compile-time error to say something like my $BankAccount::total; # Error This also means that you can have two variables of the same type and the same name, if one is a package global and one is a lexical. The following piece of code is legal, but definitely not recommended: $x = 10 ; # global to package main my $x = 20; # lexical at file scope print $x; # prints 20. Lexical variables are given priority. 6.1.2 Symbolic ReferencesSymbolic references work as we have seen earlier, for variables as well as functions. Consider package A; $x = 10; package B; # Access $A::x symbolically print ${"A::x"}; # or even more indirectly $pkg = "A"; $var_name = "x"; print ${"${pkg}::$var_name"}; # Call a subroutine indirectly &{"A::foo"}(10, 20); # Identical to A::foo(10,20); We will make extensive use of this facility in Chapter 8, Object Orientation: The Next Few Steps . |
|