Assume I have a module named Local
that exports a subroutine subLocal
via the %EXPORT_TAGS
interface.
This module is closely related to another module named Remote
that defines subroutines the user of Local
might want to import.
There are two requirements I would like to have:
Module
Local
should import the subroutines defined inRemote
only if the user of moduleLocal
is importing a subroutine defined inRemote
(either by explicitly naming the export or by using a specific export tag)When a subroutine from
Remote
is imported intoLocal
, the user of moduleLocal
should be able to refer to that subroutine as if it is in his local namespace (the same behavior you would get when referring to a subroutine defined inLocal
).
I've only found a (hacky) solution for req. 2 by adding an entry in the symbol table, but this always occurs -- regardless if the user of Local
actually needs the subroutines in Remote
. According to perldoc, this pointlessly "pollutes" the namespace.
So at what point during compilation or runtime should I be trying to import the subroutines from Remote
? And how do I actually import them in such a way that they appear in the local namespace?
This is my current approach. Module Local
:
package Local;
use strict;
use warnings;
BEGIN
{
require Exporter;
our @ISA = qw| Exporter |;
our @EXPORT_LOCAL = qw| subLocal |;
our @EXPORT_REMOTE = qw| subRemote |;
our @EXPORT_OK = ( @EXPORT_LOCAL, @EXPORT_REMOTE );
our %EXPORT_TAGS =
( all => \@EXPORT_OK, local => \@EXPORT_LOCAL, remote => \@EXPORT_REMOTE );
*subRemote = \&Remote::subRemote; # <-- can I do this conditionally somewhere?
# <-- and is there a better way to put this function in the user's local namespace?
}
use Remote; # <-- can I do this conditionally somewhere?
sub subLocal { return "(local)" }
1;
And module Remote
:
package Remote;
use strict;
use warnings;
BEGIN
{
require Exporter;
our @ISA = qw| Exporter |;
our @EXPORT_REMOTE = qw| subRemote |;
our @EXPORT_OK = ( @EXPORT_REMOTE );
our %EXPORT_TAGS =
( all => \@EXPORT_OK, remote => \@EXPORT_REMOTE );
}
sub subRemote { return "(remote)" }
1;