0

I have been USEing .pm files willy-nilly in my programs without really getting into using packages unless really needed. In essence, I would just have common routines in a .pm and they would become part of main when use'd (the .pm would have no package or Exporter or the like... just a bunch of routines).

However, I came across a situation the other day which I think I know what happened and why, but I was hoping to get some coaching from the experts here on best practices and how to resolve this. In essence, should packages be used always? Should I "do" files when I just want common routines absorbed into main (or the parent module/package)? Is Exporter really the way to handle all of this?

Here's example code of what I came across (I won't post the original code as it's thousands of lines... this is just the essence of the problem).

Pgm1.pl:

use PM1;
use PM2;
print "main\n";
&pm2sub1;
&pm1sub1;

PM1.pm:

package PM1;
require Exporter;
@ISA=qw(Exporter);
@EXPORT=qw(pm1sub1);
use Data::Dump 'dump';
use PM2;
&pm2sub1;
sub pm1sub1 {
    print "pm1sub1 from caller ",dump(caller()),"\n";
    &pm2sub1;
}
1;

PM2.pm:

use Data::Dump 'dump';
sub pm2sub1 {
    print "pm2sub1 from caller ",dump(caller()),"\n";
}
1;

In essence, I'd been use'ing PM2.pm for some time with its &pm2sub1 subroutine. Then I wrote PM1.pm at some point and it needed PM2.pm's routines as well. However, in doing it like this, PM2.pm's modules got absorbed into PM2.pm's package and then Pgm1.pl couldn't do the same since PM2.pm had already been use'd.

This code will produce

Undefined subroutine &main::pm2sub1 called at E:\Scripts\PackageFun\Pgm1.pl line 4.
pm2sub1 from caller ("PM1", "PM1.pm", 7)
main

However, when I swap the use statements like so in Pgm1.pl

use PM2;
use PM1;
print "main\n";
&pm2sub1;
&pm1sub1;

... perl will allow PM2.pm's modules into main, but then not into PM1.pm's package:

Undefined subroutine &PM1::pm2sub1 called at PM1.pm line 7.
Compilation failed in require at E:\Scripts\PackageFun\Pgm1.pl line 2.
BEGIN failed--compilation aborted at E:\Scripts\PackageFun\Pgm1.pl line 2.

So, I think I can fix this by getting religious about packages and Exporter in all my modules. Trouble is, PM2.pm is already used in a great number of other programs, so it would be a ton of regression testing to make sure I didn't break anything.

Ideas?

mswanberg
  • 1,285
  • 8
  • 20
  • So your specific question is; When you change the order of 'use' statements in your main script, does PM2 not properly load into PM1's namespace? – Jonathan Hall Nov 16 '13 at 12:11
  • Without using packages, the routine(s) will go the first place they're use'd. Which means the other package(s) must know where the routines fell and access them accordingly. I would have thought that use'ing a module without a package would put those routines into all packages that use'd them. Perhaps using "do" is the answer for this? – mswanberg Nov 17 '13 at 12:43

3 Answers3

4

See my answer to What is the difference between library files and modules?.

Only use require (and thus use) for modules (files with package, usually .pm). For "libraries" (files without package, usually .pl), use do.

Better yet, only use modules!

Community
  • 1
  • 1
ikegami
  • 367,544
  • 15
  • 269
  • 518
3

use will not load same file more than once. It will, however, call target package's import sub every time. You should format your PM2 as proper package, so use can find its import and export function to requestor's namespace from there.

(Or you could sneak your import function into proper package by fully qualifying its name, but don't do that.)

Oleg V. Volkov
  • 21,719
  • 4
  • 44
  • 68
  • Oh, I didn't realise the OP didn't understand that `require` only loads once. That's why `do` should be used here. – ikegami Jul 04 '12 at 14:44
0

You're just asking for trouble arranging your code like this. Give each module a package name (namespace), then fully qualify calls to its functions, e.g. PM2::sub1() to call sub1 in package PM2. You are already naming the functions with the package name on them (pm2sub1); it is two extra characters (::) to do it the right way and then you don't need to bother with Exporter either.

Dondi Michael Stroma
  • 4,668
  • 18
  • 21