Perl - Package / Module Issues

From all that I read when using Perl modules, the main use is:

  • A module file with the extension .pm , which includes the package <name> operator, where <name> is the name of the module file without the extension.
  • The code file that the module uses contains the use <name>; statement use <name>; .

In the application, I have one main script code that uses about 5 modules. I forgot to include the package <name> statement in the modules, but my code still did a great job with the use <name> statement. I started getting Undefined subroutine errors with one of the modules, so I added the package instruction to each of the modules. Now the rest of these modules are stopped. What gives?

Example:

mainapp.pl

 #!/usr/bin/perl use UtyDate; my $rowDate = CurrentDate("YYYYMMDD"); 

UtyDate.pm

 #!/usr/bin/perl package UtyDate; sub CurrentDate { #logic } return 1; 

When I run the above code, I get an Undefined subroutine &main::CurrentDate called at... error. However, if I remove the line package UtyDate; from UtyDate.pm, I will not get an error. This situation exists for several, but not all of my modules.

Obviously, I don’t show much more code, but I am confused about how any of the code that I don’t show can affect the package / usage constructs that I showed here.

+6
perl perl-module
source share
4 answers

When you use a module, the code in the module runs at compile time. Then the import is called in the package name for the module. So use Foo; matches BEGIN { require Foo; Foo->import; } BEGIN { require Foo; Foo->import; }

Your code worked without package declarations because all the code was executed under the main package, which is used by the main application code.

When you added package declarations, they stopped working because the routines you defined were no longer defined in main , but in UtyDate .

You can either access the routines using the fully qualified name UtyDate::CurrentDate(); , or import the routines into the current namespace when you use module.

UtyDate.pm

 package UtyDate; use strict; use warnings; use Exporter 'import'; # Export these symbols by default. Should be empty! our @EXPORT = (); # List of symbols to export. Put whatever you want available here. our @EXPORT_OK = qw( CurrentDate AnotherSub ThisOneToo ); sub CurrentDate { return 'blah'; } sub AnotherSub { return 'foo'; } 

The main program:

 #!/usr/bin/perl use strict; use warnings; use UtyDate 'CurrentDate'; # CurrentDate is imported and usable. print CurrentDate(), " CurrentDate worked\n"; # AnotherSub is not eval { AnotherSub() } or print "AnotherSub didn't work: $@ \n"; # But you can still access it by its fully qualified name print UtyDate::AnotherSub(), " UtyDate::AnotherSub works though\n"; 

See Exporter for details.

+10
source share

You are missing the perl exporter header code. You will need to add something like the following to the top of your pm file below the package instruction:

 package UtyDate; BEGIN { use Exporter (); use vars qw($VERSION @ISA @EXPORT); $VERSION = "1.0.0"; @ISA = qw(Exporter); @EXPORT = qw( &CurrentDate ); } 

See this link: http://perldoc.perl.org/Exporter.html#DESCRIPTION

+3
source share

As an alternative to Gray, you can do this:

 use UtyDate; UtyDate::CurrentDate(...); 
+1
source share

In addition to using the exporter, as Gray points out, you can (UGLY, but it works) also call functions with the module name.

You do not execute function // functions, since now they are in a different namespace (defined by the module name)

 use UtyDate; UtyDate::CurrentDate( ) 
0
source share

All Articles