Oh no, I see you only support only upper case letters only names (which would exclude @GLOBAL_SYMBOLS). Which seems too restrictive to my taste.
Don't go down on me that fast. This restriction can be lifted very easily and that's why I kept is_constant separated from push_constants. If the role of is_constant is taken by a subroutine ref, the rest is generic enough.
Here an implementation of that generic module whose idea you cherished for a moment:
package Exporter::All;
use strict;
use warnings;
use base qw(Exporter);
our $VERSION = '0.01';
use Carp qw(carp);
# these are not package symbols, but Perl artifacts
my @GLOBAL_SYMBOLS = qw(ISA EXPORT EXPORT_OK EXPORT_TAGS BEGIN );
my %EXCLUDE_LIST;
@EXCLUDE_LIST{@GLOBAL_SYMBOLS} = (1) x @GLOBAL_SYMBOLS;
sub export_all {
my $self = shift;
my %args = @_;
my $package = $args{package} || $self;
while (my ($k, $v) = each %args) {
if ($k eq 'export') {
unless ( $v eq 'CODE' ) {
carp "should be a subroutine ref";
next;
}
my $export_ref = do { no strict 'refs'; \@{ "${package}::E
+XPORT" } };
push @$export_ref, _select_symbols($package, $v);
} else {
carp "unknown parameter '$k'";
}
}
}
sub _select_symbols {
my $package = shift;
my $predicate = shift;
# iterate the package stash
my @keys = do { no strict 'refs'; keys %{$package . '::'} };
return grep {
!$EXCLUDE_LIST{$_}
&& do { no strict 'refs'; defined *{"${package}::${_
+}"}{CODE} } # has CODE slot
&& $predicate->()
} @keys
}
1;
__END__
=head1 NAME
Exporter::All - Export a bunch of symbols easily
=head1 SYNOPSIS
In the code you have symbols to export
package MyModule;
use base qw(Export::All);
MyModule->export_all( export => sub { /^my_/ } );
# these are automatically exported
sub my_home { }
sub my_office { }
In user's code
use MyModule; # imports all my_ functions
And then applying it to the original request of the OP:
package MyConstants;
use base qw(Exporter::All); # must be found in @INC
our @EXPORT;
__PACKAGE__->export_all( export => qr/^[A-Z]+$/ );
our $VERSION = 3; # it doesn't export this!
use constant FOO => 1;
use constant BAR => 2;
use constant BOO => 3;
1;
The user's code just says
use MyConstants;
to import the constants into the current namespace.
BTW I have not worried with @GLOBAL_SYMBOLS because it didn't match /^[A-Z]+$/ which does not accept underlines. It was an oversight, but, because of this, it was not a problem.
BTW you were right about using a hash. The grep was only for a quick-and-dirty solution.