Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl: Exporter doesn't work with path elements in the `use` statement

Tags:

perl

exporter

I have a perl problem: importing symbols, depending on the path elements in @INC and the use statement.

If I put the full path into @INC, the import works. If a part of the path is in the use statement the module to import is executed, but the import has to be done explicitly:

########################################
# @INC has: "D:/plu/lib/"

#------------------------------------------------
# Exporting file is here: "D:/plu/lib/impex/ex.pm"
#
use strict;
use warnings;
package ex;

use Exporter;
our @ISA = 'Exporter';
our @EXPORT = qw( fnQuark );

sub fnQuark { print "functional quark\n"; }

print "Executing module 'ex'\n";
1;

#------------------------------------------------
# Importing file, example 1, is here: "D:/plu/lib/impex/imp.pl"
#
use strict;
use warnings;
package imp;

use impex::ex;

ex->import( @ex::EXPORT );    # removing this line makes fnQuark unavailable!
                              # Why is this necessary, 'ex.pm' being an Exporter?
fnQuark();

#------------------------------------------------
#  Importing file, example 2, is here: "D:/plu/lib/impex/imp2.pl"
#
use strict;
use warnings;
package imp2;

use lib 'D:/plu/lib/impex';
use ex;

fnQuark();                    # works without explicit import
#-------------------------------------------------

What is my mistake?

like image 856
Sadko Avatar asked Jun 22 '12 08:06

Sadko


1 Answers

When you say

use Foo;

this is equivalent to:

BEGIN { 
    require 'Foo.pm';
    Foo->import;
};

You've defined the package in your ex.pm to be named ex, so when you use impex::ex, Perl does an implicit impex::ex->import. But there is no package named impex::ex, so you have to manually do the import from ex to get your symbols.

The correct way to do this is to put your modules under an existing directory in @INC and name the package after the full path-name relative to the @INC directory. So your impex/ex.pm should begin with package impex::ex; and that's how you should use it.

If you're worried about package names being long and unwieldy, have a look at aliased.

like image 57
friedo Avatar answered Nov 16 '22 09:11

friedo