Channels ▼
RSS

Web Development

Making the Most of Exporter and use


June, 2004: Making the Most of Exporter and use

Randal is a coauthor of Programming Perl, Learning Perl, Learning Perl for Win32 Systems and Effective Perl Programming, as well as a founding board member of the Perl Mongers (perl.org). Randal can be reached at merlyn@stonehenge.com.


Unless this is your first day of programming in Perl, I think it would be safe to say that you've used use at least once, and probably with some module that imports subroutines into your current package namespace. Let's take a look at precisely how that works.

As an example, let's look at the LWP::Simple module. By default, having:

use LWP::Simple;

at the top of my program means I can safely invoke get, head, getprint, getstore, and mirror, as well as a series of HTTP::Status constants, treating them as if I had written the program directly. I can narrow down that namespace pollution with a direct specification of things to import:

use LWP::Simple qw(mirror RC_OK RC_NOT_MODIFIED);

And now I get only the mirror routine and its two likely return statuses.

These invocations act as if I had included a BEGIN block wrapped around a require operation followed by a method call. For example, that latter invocation looks like this:

BEGIN {
  require LWP::Simple;
  LWP::Simple->import(qw(mirror RC_OK RC_NOT_MODIFIED));
}

Notice first that because it's a BEGIN block, we're talking about an operation that happens at compile time, not deferred until runtime. As the package name of LWP::Simple is fed to require, it is converted into an appropriate directory/subdirectory path for the architecture running the program, with a .pm extension automatically tacked on, as if we had said:

require "LWP/Simple.pm";

on a UNIX architecture machine.

Because we're using require, the @INC path is automatically consulted to locate the file. By default, this includes the system directories where Perl was installed and the current directory. We can alter the @INC path permanently by recompiling Perl, or temporarily through a combination of setting the PERL5LIB environment variable, adding a -I command-line switch, or preceding this use with either a use lib setting or something else that alters @INC at compile time.

Also, because we're using require, the .pm file must have a true value as the last expression evaluated. This is typically provided with a simple:

1;

at the end of the file; although, if you were being perverse, you could change that to:

"this line intentionally left true";

or something else as long as it was true.

Up to this point, we simply have a require operator that runs at compile-time instead of runtime, with a consistent name-management scheme to find the file. But the final step of use is the implicit method call, and this is where we get our subroutine name imports.

A typical module brought in with use will define subroutines in the package namespace appropriate to that module; for example, LWP::Simple defines LWP::Simple::get, LWP::Simple::mirror, and so on. The method call to import within LWP::Simple's class causes these names to be aliased to their same name within the invoker's namespace (typically main). This is the result of LWP::Simple inheriting from Exporter, a core Perl module that provides a relatively flexible and smart import method to handle the aliasing.

This means that LWP::Simple, like most modules, begins with something like:

package LWP::Simple;
use base qw(Exporter);

or equivalently, but backward compatible for fairly old Perl versions:

package LWP::Simple;
use vars qw/@ISA/;
require Exporter;
@ISA = qw(Exporter);

But now we've just moved the problem around a bit. The author of LWP::Simple doesn't have to write import, but Exporter::import still needs to know what to do. The Exporter::import routine looks at the @EXPORT and @EXPORT_OK variables in the current package to determine the permitted exports.

For example, LWP::Simple starts with something like:

use vars qw(@EXPORT @EXPORT_OK);
@EXPORT = qw(get head getprint getstore mirror);
@EXPORT_OK = qw($ua);

This means that, by default, the five subroutines are imported into the caller's namespace. However, any specific list of imports must come from all six names (everything in both @EXPORT and @EXPORT_OK). In truth, the exports of HTTP::Status are also added to @EXPORT, but let's ignore them for a second.

So, if I ask for:

use LWP::Simple;

I get the default list (everything in @EXPORT). If I ask for just get and mirror explictly:

use LWP::Simple qw(get mirror);

then that's all I get. If I ask for something not in the list:

use LWP::Simple qw(head tail);

then Exporter::import aborts because tail is neither @EXPORT nor @EXPORT_OK.

We can completely skip the invocation of import with an empty set of parenthesis:

use LWP::Simple ();

The $ua member of @EXPORT_OK here is actually a package variable, initially defined as $LWP::Simple::ua, but available for import into my namespace. As a rule of thumb, it's generally better to export behavior (subroutines or objects) rather than data (variables) because once your data format is "out there," it's hard to change it for future releases.

What if we want "all the default, plus this one" or "all the default, except for that one"? It turns out that Exporter::import is actually fairly flexible. We can use:

use LWP::Simple qw(:DEFAULT $ua);

to mean "all the default and $ua." Similarly, we can use:

use LWP::Simple qw(:DEFAULT !getprint !getstore);

to mean "all the default without these two listed names." Additionally, we can use regular expressions, such as:

use LWP::Simple qw(:DEFAULT !/^get/);

to mean "all the default without any name beginning with get." An expression that begins with ! appearing at the beginning of the list implies a :DEFAULT ahead of it, so we can write that last one more simply as:

use LWP::Simple qw(!/^get/);

We could even ask for:

use LWP::Simple qw(/^/);

to mean "everything that can possibly be exported" (because the regular expression of /^/ matches all possible strings).

We can define additional shortcut keywords such as :DEFAULT if subsets of our export list are frequently desired. For example, if the get routines are frequently selected or deselected as a group, we can group them as the :GET group like so:

package LWP::Simple;
use base qw(Exporter);

use vars qw(@EXPORT @EXPORT_OK %EXPORT_TAGS);
@EXPORT = qw(get head getprint getstore mirror);
@EXPORT_OK = qw($ua);
%EXPORT_TAGS = ("GET" => [qw(getprint getstore)]);

And now we can include them or exclude them easily:

use LWP::Simple qw(:GET);

which brings in only getprint and getstore, or:

use LWP::Simple qw(!:GET);

which gives us the default list, minus getprint and getstore, or even:

use LWP::Simple qw(/^/ !:GET);

which is all possible exports, except for getprint and getstore.

If /^/ is a bit mystical to explain to your users, you can help them along with an :ALL tag:

%EXPORT_TAGS = (
  "ALL" => [@EXPORT, @EXPORT_OK],
  "GET" => [qw(getprint getstore)]
);

which permits us to say:

use LWP::Simple qw(:ALL);

and get all possible exports and:

use LWP::Simple qw(:ALL !:GET);

to get everything except the getprint and getstore routines.

You can also go the other way, defining your symbols primarily in %EXPORT_TAGS, and then adding them to the @EXPORT and @EXPORT_OK variables:

package My::Package;
use base qw(Exporter);
use vars qw(%EXPORT_TAGS);
%EXPORT_TAGS = (
  "CORE" => [qw(core_enable core_disable)],
  "FIRE" => [qw(halt_and_catch_fire)],
  "VARS" => [qw($core_heat $core_fire)],
);
Exporter::export_tags('CORE', 'FIRE'); # default list
Exporter::export_ok_tags('VARS'); # optional list

Another feature of Exporter and use is the ability to check version numbers. If we include a version number before the (optional) import list, the $VERSION variable of the package will be checked to ensure that it is not smaller than the requested version. For example, if My::Package is defined as:

package My::Package;
use base qw(Exporter);
use vars qw($VERSION @EXPORT @EXPORT_OK);
$VERSION = 1.02;
@EXPORT = ...;
@EXPORT_OK = ...;

and I try to invoke it with:

use My::Package 1.05;

I will get a complaint that the version number is not sufficient. This feature is provided by the Exporter::require_version method, and compares the numbers as floating-point values. If you want a different sort of comparison, you should write your own.

Because Exporter exports a half-dozen routines into the current namespace, you might want to narrow it down to just import:

package My::Package;
use Exporter qw(import);

and now we don't have to worry about other name collisions. However, we just broke version checking, as described above, so be careful with this.

So far, we've seen most of the standard things you can do with Exporter::import. But we can also write our own import routine to do nonstandard tasks. For example, the use lib module takes the import list and adds it to @INC. The code is roughly something like:

package lib;
sub import {
  unshift @INC, @_;
}

which simply prepends the arguments passed to lib::import to the @INC path. (The actual lib module also deals with architecture-specific path additions.)

Another example of a very complex import routine is the core CGI module, which supports a version of colon-prefixed keywords as well as some other flags to trigger various actions.

You can, of course, create your own import routines as well:

package My::Package;

sub import {
  my $filename = shift;
  open MY_LOG, ">>$filename" or die;
}

and now use this as:

use My::Package qw(/my/log/file);

The indicated filename will be opened as the (package based) filehandle for logging.

Well, I think this about wraps it up for now. Hopefully, you've seen a few new ways to use your import list. Until next time, enjoy!

TPJ


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 
Dr. Dobb's TV