Документация
HTML CSS PHP PERL другое

Section 15.6.  Custom Import Routines

 
Previous
Table of Contents
Next

15.6. Custom Import Routines

Let's use CGI.pm as an example of a custom import routine before we show you how to write your own. Not satisfied with the incredible flexibility of the Exporter's import routine, CGI.pm author Lincoln Stein created a special import for the CGI module.[*] If you've ever gawked at the dizzying array of options that can appear after use CGI and wondered how it all worked, it's all a simple matter of programming. You can just look at the source yourself.

[*] Some have dubbed this the "Lincoln Loader" out of a simultaneous deep respect for Lincoln and the sheer terror of having to deal with something that just doesn't work like anything else they've encountered.

As part of the extension provided by this custom import, you can use the CGI module as an object-oriented module:

use CGI;
my $q = CGI->new;         # create a query object
my $f = $q->param('foo'); # get the foo field

or a function-oriented module:

use CGI qw(param);        # import the param function
my $f = param('foo');     # get the foo field

If you don't want to spell out every possible subfunction, bring them all in:

use CGI qw(:all);         # define 'param' and 800-gazillion others
my $f = param('foo');

And then there's pragmata available. For example, if you want to disable the normal sticky field handling, simply add -nosticky into the import list:

use CGI qw(-nosticky :all);

If you want to create the start_table and end_table routines, in addition to the others, it's simply:

use CGI qw(-nosticky :all *table);

Truly a dizzying array of options. How did Lincoln make it all work? You can just look in the CGI.pm code, see for yourself, but we'll show you the basics.

The import method is just a regular method, so we can make it do anything that we want. Earlier we showed a simple (although hypothetical) example for File::Basename. In that case, instead of using the import method from Exporter as the real module does, we wrote our own to force the symbols into the main namespace.

sub import {
  no strict 'refs';
  for (qw(filename basename fileparse)) {
    *{"main::$_"} = \&$_;
  }
}

This only works for main since that's what we hardcoded into the routine. We can figure out the calling package on the fly, however, by using the built-in caller. In scalar context, caller returns the calling package:

sub import {
  no strict 'refs';
  my $package = caller;
  for (qw(filename basename fileparse)) {
    *{$package . "::$_"} = \&$_;
  }
}

We can get even more information from caller by using it in list context.

sub import {
  no strict 'refs';
  my( $package, $file, $line ) = caller;
  warn "I was called by $package in $file\n";
  for (qw(filename basename fileparse)) {
    *{$package . "::$_"} = \&$_;
  }
}

Since import is just a method, any arguments to it (that's the import list, remember) show up in @_. We can inspect the argument list and decide what to do. Let's turn on debugging output only if debug shows up in the import list. We're not going to import a subroutine named debug. We're only going to set $debug to a true value if it's there, then do the same stuff we did before. This time we only print the warning if we've turned on debugging.

sub import {
  no strict 'refs';
  my $debug = grep { $_ eq 'debug' } @_;
  my( $package, $file, $line ) = caller;
  warn "I was called by $package in $file\n" if $debug;
  for (qw(filename basename fileparse)) {
    *{$package . "::$_"} = \&$_;
  }
}

These are the basic tricks that Lincoln used to work his CGI magic, and it's the same stuff that the Test::More module, which we introduce in Chapter 17, uses in its own import to control how testing works.


Previous
Table of Contents
Next
© 2000- NIV