After a recent discussion (constants in multiple libraries) on moving constants into modules and the benefits thereof, I swore off cut-n-paste and broke out a bunch of constants into a module by themselves, so that they could be shared with some new code.

But I ran into a problem when trying to emulate a CGI.pm feature. Exporter allows you to group together related names for export, giving the set an export 'tag' name. You can then ask for only the groups of names that you really want, e.g.

use Zowie qw( :phasers :masers :tasers !:water_pistols );
CGI.pm permits a short-cut method to export the most useful of its tagged name sets, by asking for ":all". This collects together several export tag sets so that
use CGI qw( :all );
is equivalent to, but much shorter than, saying
use CGI qw( :html2 :html3 :netscape :form :cgi :internal );

But Exporter doesn't understand how to allow you to reference a tag set that contains further references to other tag sets.

I also really liked the CGI.pm idea of listing names for export only once. (Remember I've sworn off cut-n-paste) But Exporter requires that you list all exported names in @EXPORT or @EXPORT_OK. So names I've already listed in %EXPORT_TAGS would have to be duplicated to avoid errors.

It turns out that CGI.pm has quite a bit of magic to do these things. The few other common modules that do something similar also must use magic. And while now the Perl 5.8.x Exporter documentation mentions workarounds to get nearly the same effect, that code doesn't quite do everything I want.

I wanted to be able to

Here is some code for discussion:

package LISConst; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); require Exporter; @ISA = qw(Exporter); $VERSION = '0.01'; @EXPORT = qw(); @EXPORT_OK = qw(); %EXPORT_TAGS = ( hdr_lens => [qw( LIS_TIF_HDR_LEN LIS_TIF_HDR_DATA_MAX LIS_PHY_HDR_LEN LIS_LR_HDR_LEN )], phyhdr_flags => [qw( . . . . )], lr_types => [qw( . . . . )], . . . . all => [qw( ? ? ? ? )], );

I've already listed names in the tag groups in %EXPORT_TAGS and I don't want to have to duplicate list them again in @EXPORT_OK. But Exporter will error with "LIS_TIF_HDR_LEN" is not exported by the LISConst module if I don't also get these names into @EXPORT_OK.

And what I really want for the ':all' tag set is

all => [qw( :hdr_lens :phyhdr_flags :lr_types )],
and end up with Exporter understanding that I'm exporting all the names within the referenced tag sets. Plus I'd like to be able use regular names mixed in with the set names.

After looking at the various bits of library code plus the updated documentation in Perl 5.8.x I came up with this:

{ # Expand tag names into referenced name sets my %seen; $EXPORT_TAGS{all} = [ grep { !$seen{$_}++ } map { m/^:(.*)$/ ? @{$EXPORT_TAGS{$1}} : $_ } @{$EXPORT_TAGS{all}} ]; } { # Add tag set names not already listed into @EXPORT_OK my %seen; $seen{$_}++ foreach @EXPORT_OK; push @EXPORT_OK, grep { !$seen{$_}++ } @{$EXPORT_TAGS{$_}} foreach keys %EXPORT_TAGS; }

Have y'all seen other code like this, or perhaps a better (more insightful) solution to the problem? This seems to do what I want, but sure looks oogly.


In reply to How to do "use Mumble ':all' " ala CGI.pm by shenme

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.