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

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

Dear esteemed PerlMonks

I am wrestinlg with the following issue (which may be a trivial one): how do you export functions from a package, which is not the first one in a module file? I've been searching the documentation and the Net, and can't seem to find an answer.
Here is an example:

# Name of this file: pack_A.pm package pack_A; require Exporter; @ISA = qw {Exporter}; @EXPORT = qw {first second}; sub first { } sub second { } 1; #end package pack_A; package pack_B; sub third { } sub fourth { } 1; #end package pack_B;
In the main script, I would like to use package pack_B, which sits lower in the file: pack_A.pm.
It turns out that it's not that simple. If you add the subroutines 'third' and 'fourth' to @EXPORT,
@EXPORT = qw {first second third fourth};
then in your main script, when you go:
use pack_A;
and call the 'third' sub, it will complain:
undefined subroutine &pack_A::third ...etc
(You can't go:
use pack_B;
since the interpreter looks for the file specified in "use". In other words, it will look for the module pack_B.pm, which does not exist).

Your advice will be appreciated.
Many TIA - Helen

Replies are listed 'Best First'.
Re: How to export a package sitting lower in a module?
by kennethk (Abbot) on Apr 22, 2013 at 14:59 UTC
    use is an execution of require and import wrapped in a BEGIN block. Because you have package pack_B in the same file as package pack_A, you are failing the require. So the solution is to add the export text (as Corion says) and then invoke import directly, i.e. pack_B->import.

    The better way (IMHO) to do this is to actually respect the package system intent and put pack_B in a different file, and don't surprise your maintainers.


    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      Corion and kennethk:

      It works best if you put separate packages into separate files.

      Sometimes (especially if you have an object-oriented project, with many little packages), it's not convenient to have each package in a speparate file.

      So the solution is to add the export text (as Corion says) and then invoke import directly, i.e. pack_B->import.

      Please note that this still doesn't work: the .pm module fails, complaining that the second @ISA is a bareword.

      Main script:

      use pack_A; pack_B->import; third();
      The packages:
      # Name of this file: pack_A.pm package pack_A; use strict; require Exporter; @ISA = qw {Exporter}; @EXPORT = qw {first second}; sub first { } sub second { } 1; #end package pack_A; package pack_B; use strict; require Exporter; @ISA = qw {Exporter}; @EXPORT = qw {third fourth}; sub third { } sub fourth { } 1; #end package pack_B; #end of file pack_A.pm

        Sometimes (especially if you have an object-oriented project, with many little packages), it's not convenient to have each package in a speparate file.
        If you are doing OO programming in Perl, you don't need to import anything. Using packages as libraries and exporting subroutines into a user space is actually a direct contradiction with a rigid OO model.
        Please note that this still doesn't work: the .pm module fails, complaining that the second @ISA is a bareword.
        That's because you're violating strict. Try our:
        package pack_B; use strict; require Exporter; our @ISA = qw {Exporter}; our @EXPORT = qw {third fourth}; sub third { } sub fourth { } 1;

        #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: How to export a package sitting lower in a module?
by Corion (Patriarch) on Apr 22, 2013 at 14:30 UTC

    You try to export things from pack_A by adding them to @pack_A::EXPORT. But some of these things do not live in pack_A. You will have to export things from their respective packages. In your case, that would be pack_B for third and fourth.

      Corion: can you please show how to do it?

      (You can't go:
      use pack_B;
      since the interpreter looks for the file specified in "use". In other words, it will look for the module pack_B.pm, which does not exist).

        I'm not sure how to explain "You will have to export things from their respective packages." in different words, so I'll do it by example:

        package pack_B; require Exporter; @ISA = qw {Exporter}; @EXPORT = qw {third fourth}; ...

        This is identical to the respective parts of pack_A, except with the obvious changes for pack_B.