Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Mixing configuration options and exports in 'use' statement

by Dallaylaen (Hermit)
on Dec 22, 2017 at 15:30 UTC ( #1206043=perlquestion: print w/replies, xml ) Need Help??
Dallaylaen has asked for the wisdom of the Perl Monks concerning the following question:

Hello dear esteemed monks,

I would like to be able to add per-package configuration parameters to the use statement of my module, but also let the module export some functions. Something like:

use My::Module { hairiness => 2 }, qw(:core frobnicate); frobnicate( $foo ); # with hairiness = 2

I came up with the following:

package My::Module; use parent qw(Exporter); our @EXPORT_OK = qw(frobnicate); our %EXPORT_TAGS = ( core => [], ); sub import { # or do it via a foreach and extra @args array my %setup = map { %$_ } grep { ref $_ eq 'HASH' } @_; @_ = grep { ref $_ ne 'HASH' } @_; $_[0]->per_package_setup( scalar caller, %setup ); goto \&Exporter::import; }; my %per_package_conf; # or our?.. sub per_package_setup { my ($self, $target, %options) = @_; # setup for target }; sub frobnicate { my $x = shift; return $x; # TODO actually use parameters here };

I don't want to remove exporter because it does the job and is predictable (and also has export tags).

Are there better/shorter/more common ways to do the same?

Thank you.

Replies are listed 'Best First'.
Re: Mixing configuration options and exports in 'use' statement
by pryrt (Priest) on Dec 22, 2017 at 16:34 UTC

    Don't know if there's a "better" way (for whatever definition of "better"), but it seems a pretty good method to me.

    To get your example to work, i had to add a comma between the hashref and the export list; and, of course, define dummy versions of your missing %EXPORT_TAGS and frobnicate().

    use My::Mod qw(:core frobnicate), { hairiness => 2 }; frobnicate( arg1 => 'val1' ); # with hairiness => 2
    package My::Mod; use parent qw(Exporter); our @EXPORT_OK = qw(frobnicate); our %EXPORT_TAGS = (core => []); sub import { # or do it via a foreach and extra @args array my %setup = map { %$_ } grep { ref $_ eq 'HASH' } @_; @_ = grep { ref $_ ne 'HASH' } @_; $_[0]->per_package_setup( scalar caller, %setup ); goto \&Exporter::import; }; use Data::Dumper; sub per_package_setup { my ($self, $target, %options) = @_; # setup for target print STDERR "$self->per_package_setup($target, VAR1):\n"; print STDERR Dumper \%options; %self::OPTS = %options; }; sub frobnicate { print map { "frobnicate($_)\n"} @_; printf "{ %-20s => %s }\n", $_, $self::OPTS{$_} foreach sort keys +%self::OPTS; } 1;
      Oh, didn't check it before posting. :(
Re: Mixing configuration options and exports in 'use' statement
by haukex (Abbot) on Dec 22, 2017 at 19:38 UTC

    I don't think you need goto, here's a snippet that I've often used:

    use parent 'Exporter'; sub import { # fiddle with @_ all you like here __PACKAGE__->export_to_level(1, @_); return; }
      Nice! Somehow I never did RTFM that far...

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1206043]
Approved by 1nickt
Front-paged by 1nickt
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (2)
As of 2018-02-24 09:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When it is dark outside I am happiest to see ...














    Results (310 votes). Check out past polls.

    Notices?