Re (tilly) 1: Passing parameters to a module's import function
by tilly (Archbishop) on Feb 12, 2001 at 04:34 UTC
|
Careful before saying that no such facility exists in
Exporter. There are, in fact, at least 3 ways to do this
while using Exporter.
- Use the export_to_level method.
- Do like Carp does and have flags listed in
@EXPORT_FAIL and processed in an export_fail function.
- Write a custom import that looks like this:
sub import {
my $self = shift;
my @out;
foreach (@_) {
if (ref($_)) {
# Do one thing
}
else {
push @out, $_;
}
}
@_ = ($self, @out);
goto &Exporter::import;
}
UPDATE
Two quick notes. First of all I had put the case of
Exporter wrong. Oops. Secondly the point here is that
you can preprocess the list of arguments being imported
in any way you please before Exporter sees them. (eg Take
references out of the list and do something useful with
them.) | [reply] [Watch: Dir/Any] [d/l] |
|
use MyModule { foo => 1, bar => 'two' };
are you suggesting that having Exporter.pm know about not just "foo" and "bar" but also "1" and "two" and all other possible parameter values and then having it either export them or report them as failing one at a time is somehow useful? (And your third option seems to have little to do with what was being asked.) (:
No, Exporter.pm does not provide any way of dealing with such options. You can look at Win32::TieRegistry for an example of how to parse such options while still supporting standard exporting (and non-standard exporting). But you'll probably want to ignore most of the code in Win32::TieRegistry::import as I doubt you'll want to support the strange exporting that is supported there. You might have more luck looking at Win32::TieRegistry::SetOptions.
Update: I hate this font. () and {} are nearly identical. The stuff I was talking about deals with this:
use MyModule ( foo => 1, bar => 'two' );
kind of stuff. ):
-
tye
(but my friends call me "Tye") | [reply] [Watch: Dir/Any] [d/l] [select] |
|
I gave 3 methods.
One of which I specifically said is only useful for flags.
The other two, including my actual code sample (which
was very specifically designed to handle an anonymous hash
as a case) work just fine.
| [reply] [Watch: Dir/Any] |
|
package MyModule;
use Exporter;
@ISA = qw( Exporter );
@EXPORT_OK = qw( mysub anothersub );
@ATTRIBUTES = qw( foo bar );
so that in your module you could use:
use MyModule qw( anothersub ), { foo => 1 };
It would be a good feature for Exporter. (Ideally one
would specify required attributes and maybe specify types,
default values, etc.).
UPDATE: Ok, I've corrected the formatting. Didn't realize CODE was
converted to PRE. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
First of all please use <code> tags rather than
doing your own formatting. (Cleaner, people can download
your code, etc.)
Anyways this feature makes me deeply suspicious. What is
this for? Personally I like using modules that
are designed to be used multiple times in multiple places.
This looks like it would be used to initialize a number of
globals in the module. That would mean that if I used
modules A and B which both used C, I could get hosed. But
I shouldn't need to know anything about what A and B do
internally. Therefore C should be designed so that can
be used by multiple modules at the same time without any
conflict.
Hmmmm..
I could be very wrong, but my inclination would be to ask
how your module is structured, and ask whether there is a
cleaner design that could be used. For instance use an
OO style where you pass parameters into new()...
Incidentally your comment about specifying types raises
another design flag for me. Perl is untyped, and does
not have a type system in the sense that you see in other
languages. Trying to mix concepts from a type system
with Perl is generally a sign that you are doing
something wrong (or using the wrong tool).
I don't mean to sound so down on your feature request.
Why don't you describe in more detail what a sample problem
is where you would find this useful, and we can see whether
there is another way to organize this?
| [reply] [Watch: Dir/Any] |
|
|
sub import
{
my $self = shift;
my @exports = grep { "HASH" ne ref($_) } @_;
my @options = grep { "HASH" eq ref($_) } @_;
foreach (@options)
{
# handle options here
}
@_ = ($self, @exports);
goto &Exporter::import;
}
Question: will grep interfere with @_ (making the above a bit dangerous)?
| [reply] [Watch: Dir/Any] [d/l] |
|
grep() won't do anything bad to @_, but I am personally against doing two operations in a row like you did that are complements.
That being said, I'd rewrite the @_-filtering line as:
my %args;
push @{ $args{ref($_) eq 'HASH' ? 'opt' : 'ext'} }, $_
for @_;
Or, I might even do a moving-splice() trick:
sub import {
my $self = shift;
my ($i,$j,@options);
for (@_) {
if (++$j, ref($_) eq 'HASH') {
push @options, splice(@_, $j + --$i, 1);
$_ = $_[$j+$i], redo if $j + $i < @_;
}
}
# handle @options
# @_ now only holds elements which aren't hash refs
$self->SUPER::import(@_);
}
</code>
japhy --
Perl and Regex Hacker | [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
|
Those duplicate greps bug me a bit. How about:
for (@_) {
if (ref($_) eq "HASH") {
push @options, $_;
} else {
push @exports, $_;
}
}
-- Randal L. Schwartz, Perl hacker | [reply] [Watch: Dir/Any] [d/l] |
|
Re: Passing parameters to a module's import function
by repson (Chaplain) on Feb 12, 2001 at 17:08 UTC
|
In addition to the methods above to achive what you asked,
you may like to explore other methods for whatever you are
doing.
If you are setting data within MyModule as constants
during running then other methods may be better.
# simple setting
use MyModule qw/function/;
$MyModule::foo = 1;
$MyModule::bar = 'two';
function();
# or simple function args
use MyModule qw/function/;
function( foo => 1, bar => 'two' );
# or OO
use MyModule;
my $instance = MyModule->new( foo => 1, bar => 'two' );
$instance->function;
If however you want the data in the anonymous hash to be
passed to a function which decides on exporting methods
(which is what Exporter and the import method are
usually for) the you may want to rethink if exporting in
that way is what you want. Then if you still want to do it
step back and think again. And if you still have a good
reason to do it that way that go ahead and follow the other
advice above. | [reply] [Watch: Dir/Any] [d/l] |