Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

Importing methods and configuration at the same time?

by PopeFelix (Beadle)
on Aug 29, 2013 at 17:25 UTC ( #1051486=perlquestion: print w/replies, xml ) Need Help??
PopeFelix has asked for the wisdom of the Perl Monks concerning the following question:

Suppose I want to do the following:

use MyModule 'foo' => 'bar', qw/do_something do_something_else/;

So I want to:

  • Set the global configuration value foo to 'bar'
  • import the class methods do_something and do_something_else into my namespace

Assume for this example that I don't need to be able to specify the value for foo at runtime.

I can define MyModule like so:
package MyModule; our @EXPORT_OK = qw/do_something do_something_else/; my $FOO; sub import { my ($class, %config) = @_; $FOO = $config{'foo'}; } sub do_something { if ($FOO eq 'foo') { # do something here } else { # do something else } } sub do_something_else { if ($FOO eq 'foo') { # do something else here } else { # do something other than else } } 1;

But how would I then pass ('do_something', 'do_something_else') to Exporter?

Replies are listed 'Best First'.
Re: Importing methods and configuration at the same time?
by tobyink (Abbot) on Aug 29, 2013 at 17:37 UTC

    Put the config stuff into a hashref so that it doesn't get confused with symbols to be exported.

    use MyModule { foo' => 'bar' }, qw/do_something do_something_else/;

    Your import method would go something like this:

    sub import { my $class = shift; my $config = ref($_[0]) ? shift : {}; # do stuff with $config here unshift @_, $class; # restore $class onto @_ for Exporter goto \&Exporter::import; # need to use "goto" to ensure tail call }

    The alternative would be to use Exporter::TypeTiny which has a hook called _exporter_validate_opts exactly for doing this kind of thing...

    package MyModule; use strict; use warnings; use base 'Exporter::TypeTiny'; our @EXPORT_OK = qw( something something_else ); sub _exporter_validate_opts { my ($class, $config) = @_; # do stuff with $config here }

    Though it's worth noting that the $FOO variable here is basically a global. So if two different modules use your module, they will stomp on each others' config.

    Rather than using a global variable to store your config, it's better to use a lexical, and then export functions that close over that lexical. Sub::Exporter is generally the go-to module for doing that sort of thing; Exporter::TypeTiny can as well, but currently the interface for doing so is not as clean. (It's on my todo list.)

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1051486]
Approved by sparkyichi
Front-paged by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (7)
As of 2018-05-24 14:59 GMT
Find Nodes?
    Voting Booth?