http://www.perlmonks.org?node_id=831686

crashtest has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, Monks

I have a single module file (say, Foo.pm) that defines subroutines for several packages, for example like this:

# Foo.pm package Foo::Bar; sub foo_bar_one{ ... } sub foo_bar_two{ ... } package Foo:Transforms; sub transform_one{ ... } sub transform_two{ ... } package Foo::Baz; # ... and more

What I'd like to do is to be able to use Foo and import some subroutines from a specific package in the module file into the caller's namespace (in this case, the "transform" subs). I figured I'd be able to set it up like this:

# Foo.pm package Foo; require Exporter; our @ISA = qw(Exporter); our @EXPORT_OK = qw( &Foo::transform_one &Foo::transform_two); our %EXPORT_TAGS = ( transforms => [qw( &Foo::transform_one &Foo::transform_two]); # ... rest of Foo.pm # Then in script.pl: use Foo qw(:transforms); say transform_one("xyzabc");

This doesn't seem to work - I get an undefined subroutine error; it appears none of the transform methods were exported.

I suppose I could break out the "transforms" into their own separate module and use it separately. But I was wondering if any wise Monks have advice for me on this. Is it possible to export symbols from another package (without too many gyrations?) Am I trying to do something unnatural or unadvised?

Thanks in advance for your input.

Replies are listed 'Best First'.
Re: Exporting symbols from another package
by BrowserUk (Patriarch) on Mar 29, 2010 at 19:39 UTC

    Perhaps the simplest way would be to alias the functions in the Foo namespace:

    *transform_one = *Foo::Transforms::transform_one; *transform_two = *Foo::Transforms::transform_two;

    And then your exports become just:

    our @EXPORT_OK = qw( transform_one transform_two );

    But then that questions why you've put those functions into a different namespace in the first place?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Exporting symbols from another package
by almut (Canon) on Mar 29, 2010 at 20:28 UTC

    I think what you want to do isn't directly supported by Exporter.  But you could of course reinvent the parts of it you need in slightly modified (and simplified) form:

    package Foo; use strict; use warnings; sub import { # print "Foo::import(): @_\n"; # debug shift @_; # first arg not needed here my $dest = caller; for my $what (@_) { if ($what eq ':transforms') { no strict 'refs'; for (qw(transform_one transform_two)) { *{"${dest}::$_"} = *{"Foo::Transforms::$_"}; } } # elsif ... } } package Foo::Transforms; sub transform_one{ return "transform_one(): @_" } sub transform_two{ return "transform_two(): @_" } # ... 1;
    #!/usr/local/bin/perl -l use Foo qw(:transforms); print transform_one("xyzabc"); __END__ $ ./831686.pl transform_one(): xyzabc

    The difference to the other suggestions is that you wouldn't need to go exporting indirectly via the Foo namespace.  In other words, you could have routines of the same name in Foo::Bar, Foo::Transforms, etc. without risking name clashes in the intermediate Foo namespace... (of course, the mapped final names in the destination package would still have to be unique).

Re: Exporting symbols from another package
by Hue-Bond (Priest) on Mar 29, 2010 at 20:36 UTC

    When I wanted to achieve something like that, this is what I did:

    package Foo::One; use warnings; use strict; use base qw/Foo Exporter/; our @EXPORT_OK = qw/action1/; sub action1 { ... } package Foo::Two; use warnings; use strict; use base qw/Foo Exporter/; our @EXPORT_OK = qw/action2/; sub action2 { ... } package Foo; MHT::One->import (qw/action1/); MHT::Two->import (qw/action2/); our %EXPORT_TAGS = ( One => [qw/action1/], Two => [qw/action2/], ); Exporter::export_ok_tags keys %EXPORT_TAGS;

    And later:

    use Foo qw/:One :Two/;

    Which is basically what BrowserUk suggests.

    --
     David Serrano
     (Please treat my english text just like Perl code, i.e. feel free to notify me of any syntax, grammar, style and/or spelling error. Thank you!).

Re: Exporting symbols from another package
by zwon (Abbot) on Mar 29, 2010 at 19:26 UTC

    That should be just

    our @EXPORT_OK = qw(transform_one transform_two);

    Update: sorry, I didn't read the question carefully enough. As BrowserUk noted you should first import functions into Foo.

      Wouldn't he have to import the functions from the Foo::Transfoms namespace into the Foo namespace before he could export them from the Foo namespace?


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.