Reputation: 38714
I have a Perl module and I'd like to be able to pick out the parameters that my my module's user passed in the "use" call. Whichever ones I don't recognize I'd like to pass on. I tried to do this by overriding the "import" method but I'm not having much luck.
EDIT:
To clarify, as it is, I can use my module like this:
use MyModule qw/foo bar/;
which will import the foo and bar methods of MyModule. But I want to be able to say:
use MyModule qw/foo doSpecialStuff bar/;
and look for doSpecialStuff to check if I need to do some special stuff at the beginning of the program, then pass qw/foo bar/ to the Exporter's import
Upvotes: 4
Views: 277
Reputation: 53966
Normally, you would do this to gain Exporter's import() functionality (this isn't the only way, but it's a common method that works):
package MyClass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our @EXPORT_OK = qw(stuff more_stuff even_more_stuff);
...and then you will get an import()
method automatically created for you. However, if you want to do something extra in import()
before the normal method gets a hold of the parameters, then don't import Exporter's import()
, and define your own, which calls Exporter's import()
after making any alterations to the argument list that you need:
package MyClass;
use strict;
use warnings;
use parent 'Exporter';
sub import
{
my ($class, @symbols) = @_;
# do something with @symbols, as appropriate for your application
# ...code here left as an exercise for the reader :)
# now call Exporter's import, and import to the right level
local $Exporter::ExportLevel = 1;
$class->SUPER::import(@symbols);
}
However, I'm wondering why you need to do this... the standard behaviour of dying when being passed an unrecognized symbol is normally a good thing. Why would you want to ignore unrecognized symbols? (Edit: I see now, you want to specify additional behaviour on top of importing symbols, which is not uncommon in Perl. So defining your own import() method is definitely the way to go here, to grab those values.)
PS. if you only want to import symbols which are defined by @EXPORT_OK, it could be implemented like this:
@symbols = grep {
my $sym = $_;
grep { $_ eq $sym } @EXPORT_OK
} @symbols;
Upvotes: 8
Reputation: 40142
I have done it this way in my modules:
sub import {
return if not @_;
require Exporter;
my $pkg = shift;
# process @_ however you want
unshift @_, $pkg;
goto &Exporter::import;
}
you can also inherit from Exporter if you want unimport and the like.
Upvotes: 2
Reputation: 118605
The typical use of Exporter
is to declare your module to inherit from Exporter
, and to have Exporter
's import
method called implicitly when your module is used. But this keeps you from creating your own import
method for your module.
The workaround is to use Exporter's export_to_level
method, which performs Exporter
's functions without explicitly going through the Exporter::import
method. Here's a typical way to use it:
package My::Module;
use base 'Exporter'; # or use Exporter; our @ISA=qw(Exporter);
our @EXPORT = qw(...);
our @EXPORT_OK = qw(...);
our %EXPORT_TAGS = (...);
sub import {
my ($class,@import_args) = @_;
my @import_args_to_pass_on = ();
foreach my $arg (@import_args) {
if (... want to process this arg here ...) {
...
} else {
push @import_args_to_pass_on, $arg;
}
}
My::Module->export_to_level(1, "My::Module", @import_args_to_pass_on, @EXPORT);
#or: $class->export_to_level(1, $class, @import_args_to_pass_on, @EXPORT);
}
Upvotes: 3