10.3. Using do
The Skipper placed a few common navigation subroutines into navigation.pm . If the Skipper merely inserts:
do 'navigation.pm'; die $@ if $@;
into his typical navigation program, it's almost the same as if the eval code were executed right at that point in the program. [ ]
That is, the do operator acts as if the code from navigation.pm were incorporated into the current program, although in its own scope block, so that lexicals ( my variables) and most directives (such as use strict ) from the included file don't leak into the main program.
Now the Skipper can safely update and maintain one copy of the common subroutines without having to copy and recopy all the fixes and extensions into the many separate navigation programs he creates and uses. Figure 10-1 illustrates how the Skipper can use his common library.
Figure 10-1. The Skipper uses the navigation.pm file in all his other navigation programs
Of course, this requires a bit of discipline, because breaking the expected interface of a given subroutine now breaks many programs instead of just one. [ ] The Skipper needs to give special thought to his design for reusable components and modularity design. Well presume the Skipper has had some experience at that, but we'll show some more on that in later chapters.
By placing some of the code into a separate file, other programmers can reuse the Skipper's routines, and vice versa. If Gilligan writes a routine to drop_anchor( ) and places it in the file drop_anchor.pm , then the Skipper can use Gilligan's code by including his library:
do 'drop_anchor.pm'; die $@ if $@; ... drop_anchor( ) if at_dock( ) or in_port( );
Thus, the code that we bring in from separate files permits easy maintenance and interprogrammer cooperation.
While the code we brought in from a .pm file can have direct executable statements, it's much more common to simply define subroutines that we can load using do .
Going back to that drop_anchor.pm library for a second, what if the Skipper wrote a program that needed to "drop anchor" as well as navigate?
do 'drop_anchor.pm'; die $@ if $@; do 'navigation.pm'; die $@ if $@; ... turn_toward_heading(90); ... drop_anchor( ) if at_dock( );
That works fine and dandy. The subroutines defined in both libraries are available to this program.
10.4. Using require
Suppose navigation.pm itself also pulls in drop_anchor.pm for some common navigation task. Perl reads the file once directly and then again while processing the navigation package. This needlessly redefines drop_anchor( ) . Worse than that, if we have warnings enabled, [*] we'll get a warning from Perl that we've redefined the subroutine, even if it's the same definition.
We need a mechanism that tracks which files we've brought in and then
require 'drop_anchor.pm'; require 'navigation.pm';
operator keeps track of the files Perl has read.
Once Perl has
Figure 10-2. Once Perl brings in the drop_anchor.pm file, it ignores another attempt to require it
The require operator also has two additional features:
Because of the second point, most files evaluated for require have a cryptic 1; as their last line of code. This ensures that the last evaluated expression is, in fact, true. Try to carry on this tradition as well.
Originally, the mandatory true value was intended as a way for an included file to signal to the invoker that the code was processed successfully and that no error condition existed. However, nearly everyone has adopted the die if ... strategy instead, deeming the "last expression evaluated is false" strategy a mere historic annoyance.