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

1

9

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?

Horologist answered 22/6, 2012 at 8:51 Comment(0)
G
10

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.

Gainsborough answered 22/6, 2012 at 9:16 Comment(1)
Thank you for the quick reply. But I do not understand why I didn't have this problem before. I have so many modules, e. g. 'FotoArchive.pm' in lib/Foto, with the package name FotoArchive and Foto not in the @INC path. Why does that not cause the same problems when I invoke them via Foto::FotoArchive? -- Ah, I begin to see, because they don't export anything. So I got away with my mistake unnoticed for so long! Thank you!Horologist

© 2022 - 2024 — McMap. All rights reserved.