netdjw
netdjw

Reputation: 6007

Perl `use qw` or import subroutines from pm files

I have a perl module .pm file what containts my subroutines and it looks like this:

package test;
use strict;
use vars qw($VERSION @ISA @EXPORT $ERROR $NAME);
require Exporter;
@ISA  = qw(Exporter);
@EXPORT = (
    sub1
    sub2
    err1
    err2
);
#...etc...

Now I have a pl file, what need to import subroutines, but not every one, only if they are in the configured list. For example:

@subs = ('sub1', 'sub2'); # need to load sub1 & sub2, but do not load err1 & err2

or

@subs = ('sub1', 'err1'); # need to load sub1 & err1, but do not load sub2 & err2

How can I do this?

I tried to do this, but not working:

my @subs = ('sub1', 'sub2');
use test @subs;

Is there any way to load only the needed functions? And what is needed is read from SQL or config file or any other way...

Upvotes: 3

Views: 4732

Answers (2)

Ilmari Karonen
Ilmari Karonen

Reputation: 50368

The reason your code:

my @subs = ('sub1', 'sub2');
use test @subs;

doesn't work is that use statements are evaluated immediately during parsing, before (almost) any other code. Thus, the second line of your code actually runs before the first one, and so @subs is still empty at that point.

This would work:

my @subs;
BEGIN { @subs = ('sub1', 'sub2'); }
use test @subs;

as would this:

BEGIN {
    my @subs = ('sub1', 'sub2');
    require test;
    test->import(@subs);
}

In the former version, the BEGIN block is used to make the assignment to @subs happen already during parsing; in the second version, the entire code is put inside a BEGIN block, and the use statement is replaced with its run-time equivalent (require + import).


However, you probably don't have any reason to do this in the first place. When you load a module, all of its code is loaded anyway,* so you don't actually save any memory by just importing some of the functions the module provides. In fact, just about the only real reason not to import everything a module provides is to avoid conflicts between modules that might be trying to export functions with the same name, or with your own function.

In any case, it's always* possible to call functions in a module without importing them at all, just by prefixing them with the module name and ::. So, instead of:

use test qw(foo bar);
foo();
bar();

you can just do:

use test ();
test::foo();
test::bar();

*) Technically, there are few things that are guaranteed in Perl, and it's quite possible for a module to implement some kind of a lazy-loading mechanism that only creates functions (or loads them from another module) when you import them. But that requires a custom import (and/or AUTOLOAD) method; for ordinary modules using Exporter, the simplified description above is true.

Upvotes: 8

Borodin
Borodin

Reputation: 126742

First of all, all Perl globals should use capital letters, so the name of your package should begin with capital letter, and the name of the file should be altered to agree

Secondly, there is much less overhead if, instead of inheriting from Exporter, you load its import method directly

I don't understand what sort of thing err1 and err2 are, but should put optional exports in the array @EXPORT_OK

That leaves your module looking like this

Test.pm

package Test;

use strict;
use warnings;

use Exporter 'import';

our @EXPORT_OK = qw/ sub1 sub2 /;

sub sub1 {
  print "sub1\n";
}

sub sub2 {
  print "sub2\n";
}

and a program that uses it would look like this

use strict;
use warnings;

use Test qw/ sub1 /;

sub1;

output

sub1

Upvotes: -1

Related Questions