duane_ellis has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

I've got a dozen or so of modules in a directory - (ie: FOO_X.pm, FOO_Y.pm, etc..) And a some scripts (ie: A.pl, B.pl, C.pl, etc) that make use of them. The size/scope of the modules is too large to puthere (and they require access to a database to work) Creating tiny test examples work fine. I have not got a small reproducable example yet. The modules are collections of like minded routines. ie: Report.pm, Schedule.pm, Tasks.pm, Orders.pm. The scripts live in a "bin" directory, and the modules live in a "lib" directory.

For some reason, I seem to have random "undefined subroutine" problems that I cannot explain.

BEGIN SHORT DESCRIPTION: The problem is like this:

If I execute script A, which uses Module X - which then uses module Y - then Z... it works.

If I execute script B, which begins with a different module, which - uses modules just like A, andin the end - uses Y, and Module Z... it does not.

The path that script B takes causes causes Y's references to Z to fail as undefined subroutines.

The only known work around I have is to fully qualify every access to Z's functions. (ie: In the form: ModName::FuncName) I should not have to do that.

END SHORT DESCRIPTION

Longer description graphically - its like this:

A -> use FOO_ModuleX; -> use FOO_Module_Y; -> use FOO_Module_Z
By that, I mean: script A uses Module X directly. Module X uses Y, Module Y - then uses Module Z. My script does not reference Z it directly

Script B, enters the maze from a different location, somewhere along the way - something it uses Y, which uses Z... and that is the problem.

The scripts start with the same boilerplate, and look like this:

#! /usr/bin/perl use strict; use warnings; # Std Perl Modules use Carp; use File::Copy; ... actual list varies depends on script ... # Our modules. use FOO_X; ... actual list varies depends on script ... #======================= # Code begins... # A trivial example my $msg = foo_x_function( "hello" ); print "$msg\n" exit 0;

NOTE: I do not know if this matters: I do not "use *.pm" (ie: a "use" statement for every one of my modules in every one of my modules.... However but the "use" hierachy is not purely recursive, the modules are 'mutually recursive'. Huh? you ask... I am not using recursion... I'm describing the 'use Name;' relationship between *MY* modules.., like this:

A use relationship graph between my modules could be described as Spagetti.

The problem seems to be related to the 'use relationship path' or it is a namespace/scoping problem.

I've read - quite a number of things - with no luck For example:

Technical details...
================================ PERL Version: (host RH EL4 - intel) This is perl, v5.8.5 built for i386-linux-thread-multi ================================ ====================================== The style/format of my modules are like this: (From: http://perldoc.perl.org/perlmod.html example) ====================================== #! /usr/bin/perl package NameX; use strict; use warnings use NameY; use NameZ; BEGIN { use Exporter (); our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS ); $VERSION = 1.00; @ISA = qw( Exporter ); @EXPORT = qw ( &func1 &func2 ); %EXPORT_TAGS = (); @EXPORT_OK = qw(); } sub func1 { } sub func2 { } ======================
To answer some questions I've seen asked before: Remember - it works - if I execute it via one script, but does not work if I execute it via another script.

At this point, I'm at a loss to figure this out. When I have problems like this in C code, I resort to the preprocessor output and other things like that... I don't know how to do things like that with perl. For example: Is there a means to have perl explain what it is doing During a use statement... perhaps something like this would help me:

use Works_First; TURN_ON_MAGIC_HERE; use ProblemModule; TURN_OFF_MAGIC_HERE; use OtherModules;
Thanks, --Duane.

Replies are listed 'Best First'.
Re: Module Undefined Subroutines, works one way - not another
by ikegami (Patriarch) on Jan 11, 2007 at 17:53 UTC

    You have a case where ModA uses ModB (indirectly) and ModB uses ModA.

    If ModA uses ModB, ModB uses ModA, and both ModA and ModB export symbols, you have a bad design.

    If ModA uses ModB, ModB uses ModA, and both ModA and ModB export symbols, one needs to pay attention to code execution order. The best way I've found to avoid problems is to do:

    # ModA.pm use strict; use warnings; package ModA; BEGIN { our @ISA = qw( Exporter ); our @EXPORT_OK = qw( ... ); require Exporter; } use This; use ModB; use That; ... 1;
    # ModB.pm use strict; use warnings; package ModB; BEGIN { our @ISA = qw( Exporter ); our @EXPORT_OK = qw( ... ); require Exporter; } use This; use ModA; use That; ... 1;

    Basically, move your use statments from where they to after your BEGIN.

      If ModA uses ModB, ModB uses ModA, and both ModA and ModB export symbols, you have a bad design.

      I do not think creating ONE huge source module with 300K to 500K of code is a good idea... That's why I broke the modules up into functionality areas. ie: "Report", "User", etc...

      Perhaps I come from an old school - no function - longer then 1 or 2 screens, and group "like functions" into the same file.

      The modules use each other - effectively via "callbacks", yea, I could pass pointers to functions etc... but that overly complicates the matter *because* they will never call any other function other then then one.

      I'll try what you suggest, move the USE ater the BEGIN statements.

      I note specifically your example also has a few USE items before, then the begin, then my rats nest of USE statements. Do you mean that specific order is important? I presume the problem (my) modules go last.

      Thanks... -Duane.

        I note specifically your example also has a few USE items before

        Aye, but strict and warnings don't use any module which use them, strict and warnings don't export anything to modules from which they import, and they are pragmas more than modules.

        They are before the BEGIN block so that they affect the code before and in the BEGIN block.

Re: Module Undefined Subroutines, works one way - not another
by almut (Canon) on Jan 11, 2007 at 18:58 UTC

    ( Not sure whether I have correctly digested every bit of information you supplied (quite a lot to read :) -- so in case I misinterpreted something, just ignore my post...)

    You are aware that symbols are exported only into the namespace of the module from which the use is being issued, are you?

    A simple example. Assume the following definitions

    package X; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(func_in_X); use Y; sub func_in_X { print "func_in_X called.\n"; } 1; --- package Y; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(func_in_Y); sub func_in_Y { print "func_in_Y called.\n"; } 1;

    Now, if you only use X in your script:

    #!/usr/bin/perl use X; # X uses Y secondarily # this works func_in_X(); # imported into our namespace Y::func_in_Y(); # fully qualified X::func_in_Y(); # fully qualified via namespace X, # into which func_in_Y() has been exported # this doesn't work func_in_Y(); # not imported into our namespace

    A simple way around this is to explicitly use every module, of which you need any symbols in your current namespace.

Re: Module Undefined Subroutines, works one way - not another
by ysth (Canon) on Jan 12, 2007 at 08:01 UTC