Search code examples
perl

Multiple package with Exporter


I'm trying to get familiar with Perl Exporter. The issue I am facing is whatever I try, I cannot use Exporter with modules containing multiple packages in it. What am I missing below?

MyModule.pm

use strict;
use warnings;

package Multipackage1;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(test1);

sub test1 {

  print "First package\n";
  
}

1;

package Multipackage2;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(test2);

sub test2 {

   print "Second package\n";
   
}

1;

package Multipackage3;
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(test3);

sub test3 {

   print "Third package\n";
   
}

1;

MyMainFile.pl

#!/usr/bin/perl 

use strict;
use warnings;
use Multipackage;
use Multipackage qw(test3);

print "Calling first package:\n";
test1();
print "Calling second package:\n";
test2();
print "Calling third package:\n";
test3();

I'm getting test1 is not part of the main package.


Solution

  • The use calls require, which looks for a file with the package name (with / for :: and + .pm).

    So require the actual file with packages instead and then import from packages.

    main.pl

    use warnings;
    use strict;
    
    require MyModule;
    
    import Multipackage1;
    import Multipackage2;
    import Multipackage3 qw(test3);
    
    print "Calling first package:\n";
    test1();
    print "Calling second package:\n";
    test2();
    print "Calling third package:\n";
    test3();
    

    In MyModule.pm, place each package in its own block to provide scope for lexical variables since package doesn't do that, or use package Pack { ... } since v5.14. There is no need for all those 1s, and you may pull use Exporter; out of the blocks.

    Output

    Calling first package:
    First package
    Calling second package:
    Second package
    Calling third package:
    Third package
    

    Better yet, replace our @ISA = qw(Exporter); with use Exporter qw(import); for

    use strict;
    use warnings;
    
    package Multipackage1 {
        use Exporter qw(import);
        our @EXPORT = qw(test1);
    
        sub test1 { print "First package\n" }
    }
    ...
    1;
    

    with the same output. See Exporter.

    Note that putting multiple packages in one file is normally not needed and not done.