
![]() | ![]() |
12.3. Delaying use Until Runtime
12.3.1. Problem
You have a module that you don't need to
load each time the program runs, or whose inclusion you wish to delay
until after the program starts up.
12.3.2. Solution
Either break up the use into its separate
require and import components,
or else employ the use autouse
pragma.
12.3.3. Discussion
Programs that check their arguments and abort with a usage message on
error have no reason to load modules they never use. This delays the
inevitable and annoys users. But those use
statements happen during compilation, not execution, as explained in
the Introduction.Here, an effective strategy is to place argument checking in a BEGIN
block before loading the modules. The following is the start of a
program that checks to make sure it was called with exactly two
arguments, which must be whole numbers, before going on to load the
modules it will need:BEGIN {
unless (@ARGV = = 2 && (2 = = grep {/^\d+$/} @ARGV)) {
die "usage: $0 num1 num2\n";
}
}
use Some::Module;
use More::Modules;
A related situation arises in programs that don't always use the same
set of modules every time they're run. For example, the
factors program from Chapter 2 needs the infinite precision arithmetic
library only when the -b
command-line flag is supplied. A use statement
would be pointless within a conditional because it's evaluated at
compile time, long before the if can be checked.
So we use a require instead:if ($opt_b) {
require Math::BigInt;
}
Because Math::BigInt is an object-oriented module instead of a
traditional one, no import was needed. If you have an import list,
specify it with a qw( ) construct as you would
with use. For example, rather than this:use Fcntl qw(O_EXCL O_CREAT O_RDWR);
you might say this instead:require Fcntl;
Fcntl->import(qw(O_EXCL O_CREAT O_RDWR));
Delaying the import until runtime means that the rest of your program
is not subject to any imported semantic changes that the compiler
would have seen if you'd used a use. In
particular, subroutine prototypes and the overriding of built-in
functions are not seen in time.You might want to encapsulate this delayed loading in a subroutine.
The following deceptively simple approach does not work:sub load_module {
require $_[0]; #WRONG
import $_[0]; #WRONG
}
It fails for subtle reasons. Imagine calling
require with an argument of
"Math::BigFloat". If that's a bareword, the double
colon is converted into your operating system's path separator and a
trailing .pm is added. But as a simple variable,
it's a literal filename. Worse, Perl doesn't have a built-in
import function. Instead, there's a class method
named import that we're using the dubious indirect
object syntax on. As with indirect filehandles, you can use indirect
objects only on a plain scalar variable, a bareword, or a block
returning the object, not an expression or one element from an array
or hash.A better implementation might look more like:load_module("Fcntl", qw(O_EXCL O_CREAT O_RDWR));
sub load_module {
eval "require $_[0]";
die if $@;
$_[0]->import(@_[1 .. $#_]);
}
But this still isn't perfectly correct in the general case. It really
shouldn't import those symbols into its own package. It should put
them into its caller's package. We could account for this, but the
whole procedure is getting increasingly messy.Occasionally, the condition can be reasonably evaluated before
runtime, perhaps because it uses only built-in, predefined variables,
or because you've arranged to initialize the variables used in the
conditional expression at compile time with a BEGIN block. If so, the
if pragma comes in handy. The syntax is:use CONDITION, MODULE;
use CONDITION, MODULE => ARGUMENTS;
As in:use if $^O =~ /bsd/i, BSD::Resource;
use if $] >= 5.006_01, File::Temp => qw/tempfile tempdir/;
A convenient
alternative is the use autouse
pragma. This directive can save time on infrequently loaded functions
by delaying their loading until they're actually used:use autouse Fcntl => qw( O_EXCL( ) O_CREAT( ) O_RDWR( ) );
We put
parentheses after O_EXCL,
O_CREAT, and O_RDWR when we
autouse d them but not when we
used them or import ed them. The
autouse pragma doesn't just take function names;
it can also take a prototype for the function. The Fcntl constants
are prototyped to take no arguments, so we can use them as barewords
in our program without use
strict kvetching.Remember, too, that use
strict's checks take place at compile time. If we
use Fcntl, the prototypes in
the Fcntl module are compiled and we can use the constants without
parentheses. If we require or wrap the
use in an eval, as we did
earlier, we prevent the compiler from reading the prototypes, so we
can't use the Fcntl constants without parentheses.Read the autouse pragma's online documentation to
learn its various caveats and provisos.
12.3.4. See Also
Recipe 12.2; the discussion on the
import method in the documentation for the
standard Exporter module, also found in Chapter 32 of
Programming Perl; the documentation for the
standard use autouse
pragma
![]() | ![]() | ![]() |
12.2. Trapping Errors in require or use | ![]() | 12.4. Making Variables Private to a Module |

Copyright © 2003 O'Reilly & Associates. All rights reserved.