I'm working on a non-OO module that has a number of subs that are dynamically created and added to the symbol table. Their names are known at compile time, so I could certainly hard-code them in, but I'm a fan of DRY and would rather just specify them once.
When the module is loaded I have several subs that are string-eval'd into existence. In reality the body of the subs is more complex than a simple tr//, but this demonstrates the problem well enough. Everything works fine, but I'm stuck on the simple task of convincing Exporter::Easy to export the subs. I can make it work with Exporter just fine:
package Foo; use strict; use warnings; use Carp; my %subs = ( subA => _gen_tr('abc' => 'xyz'), subB => _gen_tr('ijk' => 'qrs'), ); $subs{reverse($_)} = $subs{$_} for keys %subs; # Stand-in example for +aliases no strict 'refs'; *$_ = $subs{$_} for keys %subs; require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = keys %subs; sub _gen_tr { /^\w+$/ or confess "Non-word characters in argument: <$_>" for @_; eval "sub { shift =~ tr/$_[0]/$_[1]/r }" } 1;
The above works fine; all subs and their aliases are exported as expected (passes test code at the end of this post).
But when I replace the require Exporter; our @ISA ...; our @EXPORT_OK ...; lines with a similar Exporter::Easy incantation:
use Exporter::Easy ( OK => [ keys %subs ], TAGS => [ all => [ keys %subs ], ], );
Code using Foo sees "subA" is not exported by the Foo module, whether I use Foo ':all' or specify subA directly. I've even tried wrapping the exports and actual %subs initialization in a BEGIN block, but that did not make a difference. Hardcoding the sub names directly in the OK => [ ... ] or all => [ ... ] lines does of course work, but that's exactly what I'm trying to avoid doing.
Why Exporter::Easy? One reason is, I like it. The "real" reason is, my full code has more tags and more complex exports. I can do what I want with Exporter, but it's ugly. I'm willing to consider other Exporter::* modules if Exporter::Easy can't handle it. Or, I suppose, to suck it up and use Exporter if there's no other way.
So how would you do it? $cake->have->eat;
Test code:
use strict; use warnings; use Test::More; # Pick one: #use Foo qw/subA subB Abus Bbus/; use Foo ':all'; is subA('abra-cadabra'), 'xyrx-zxdxyrx'; is subB('i like stuff'), 'q lqse stuff'; is Abus('abra-cadabra'), 'xyrx-zxdxyrx'; is Bbus('i like stuff'), 'q lqse stuff'; done_testing;
In reply to Dynamic exports with Exporter::Easy by wanna_code_perl
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |