I was about to write up a module that exports lots of functions. It's for testing purposes to create interesting, semi-random, complicated objects for testing which I refer as "The Sims" -- in the "let's create people and then throw them into a torturous environment and see how they react" sense.
Anyhow, it's going to export a huge pile of sim_* functions (whether or not that's a good idea is immaterial). I don't want to have to remember to update an @EXPORT variable dissociated from declaring the function. I'm going to forget. The obvious answer would seem to be to make exporting an attribute of the subroutine. And that's just what Exporter::Simple does. Unfortunately it doesn't really work and there doesn't appear to be an easy fix.
So...
* Is there an existing module that works and does what I want?
* If not, can Exporter::Simple be fixed?
* If not, could you write an Export-by-attribute system that does work?
* If not, could you write something that allows the export information to be conveniently placed near the subroutine?
Re:Answers...
rjbs on 2008-01-25T15:42:45
I think Adam's solution (push onto @EXPORT) is pretty nice and simple, as far as things that deal with attributes can be. It's exactly what I would've suggested, although I probably would've built atop Sub::Exporter.;)
I'll be interested to hear/see what you end up doing.
If in fact your module simply needs to "export a huge pile of sim_* functions", then one solution would be to write your own import()
sub that scans your package's symbol table hash and exports every sub with a name that matches/^sim_/
.
I'm the author of Exporter::Simple. It has some other bugs as well, and there's, like you said, no simple fix. Maybe Damian's Perl6::Export does what you want? The only thing - as far as I can remember - that Exporter::Simple does additionally is to be able to export variables, which Damian says is evil anyway. If Perl6::Export works better, then I was planning to deprecate Exporter::Simple.
Well to start with, please please please make sure it's based on Sub::Exporter and not Exporter.pm. And as for basing it on attributes, I don't think that is a plus. Attributes are poorly implemented with a poor API to use them. They give you just enough power to think you can do something cool with them, and then fall short (IMO at least).
Okay, that said, here is a modified version of a proof of concept module I did recently that mixed Moose roles and Sub::Exporter. It should do the trick for exporting all ^sim_*
functions without having to repeat yourself in @EXPORT or in attributes.
You would then use it in your module like sopackage Export::Only::What::I::Want;
use strict;
use warnings;
use Class::MOP;
use Sub::Exporter;
sub import {
shift;
my ($regexp) = @_;
my $pkg = caller();
my $pkg_meta = Class::MOP::Class->initialize($pkg);
$pkg_meta->alias_method(import => Sub::Exporter::build_exporter(
{
exports => {
map {
$_ => $pkg_meta->get_method($_)->body
} grep {
/$regexp/
} $pkg_meta->get_method_list
},
groups => { default => [':all'] }
}
)
);
}
And whalla...package Foo;
use Export::Only::What::I::Want qr/^foo_/;
sub foo_bar { 'Foo::foo_bar' }
sub bar_foo { 'Foo::bar_foo' }
package Bar;
use Foo;
# Bar::foo_bar exists, but no Bar::bar_foo..
- Stevan