(tye)Re: Passing parameters to a module's import function
by tye (Sage) on Feb 12, 2001 at 08:46 UTC
|
Um, tilly, in the sample usage:
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] [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] |
Re: Re (tilly) 1: Passing parameters to a module's import function
by rrwo (Friar) on Feb 13, 2001 at 06:44 UTC
|
I've already been experimenting with something like the import
function you've shown. But by "no such facility exists in Exporter"
I mean that you can't have the following in your module:
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] [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] |
|
Your point about multiple modules using it is a good one. However,
this module is not likely to be used by anything other than a main
program (it's a version of Win32::EventLog::Carp which
traps warnings and fatals and posts them in the Windows NT event log;
I'd like to give the option of specifying a different source name,
so that related scripts can show up in the logs using one name
than each individual script's file name.)
I'm experimenting with various ways to handling this. By specifying
these options upon importing, compilation errors and warnings will be
logged under the parameters specified--as "FooProject" rather than "index.pl"
and logged in the System log rather than Application log, for instance.
This is a very specialized case, so it probably would make more sense
in a separate module which extends Exporter rather than Exporter. But there are
cases where one may want to pass some configuration information to the module.
As for specifying types, that feature isn't important to me. Sometimes people want
it.
| [reply] [d/l] |
An alternate way of implementing import with options
by rrwo (Friar) on Feb 13, 2001 at 20:57 UTC
|
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] [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] [d/l] [select] |
|
| [reply] |
|
|
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] [d/l] |
|
That is morally the same as my original version. In fact
before I posted I had thought about having 2 arrays,
and then I thought that instead of tracking options, it
probably made more sense to process in place. :-)
| [reply] |