in reply to Namespace and use confusion. "Undefined subroutine errors"

The simple answer is don't do that! Modules calling each other or calling themselves are usually a sign of bad design.


Putting aside the validity of your design, let's first find the cause of the problem. Keep in mind that

use Module LIST;

is the same as

require Module; Module->import LIST if Module->can('import');

while we look, line by line, at the code Perl executes:

test1.pl:2 use strict; test1.pl:4 use lib qq{/usr/web/wonko/test/lib/SYS}; test1.pl:5 use lib qq{/usr/web/wonko/test/lib/AB}; test1.pl:7 require SYS_mail; Start executing SYS_mail.pm SYS_mail.pm:1 package SYS_mail; SYS_mail.pm:3 use lib qq{/usr/web/wonko/test/lib/AB}; SYS_mail.pm:5 require AB_prod; Start executing AB_prod.pm AB_prod.pm:1 package AB_prod; AB_prod.pm:3 use lib qq{/usr/web/wonko/test/lib/SYS}; AB_prod.pm:5 require SYS_mail; Does nothing. Already required AB_prod.pm:5 SYS_mail->import(qw ( send_mail )) if SYS_mail->can('import'); ERROR!!

The error is that we haven't yet executed

use vars qw(@ISA @EXPORT_OK); use Exporter(); @ISA = qw(Exporter); @EXPORT_OK = qw( send_notice );

in SYS_mail.pm, so SYS_mail has no import function, so send_mail doesn't get imported into AB_prod. Similar errors occur at later points in the program.


And now the fix:

To fix this problem (aside from the obvious one of not including yourself directly or indirectly), change your modules to the following:

/usr/web/wonko/test/AB/AB_prod.pm #-------------------------------------------------------------------- package AB_prod; use lib qq{/usr/web/wonko/test/lib/SYS}; use strict; use warnings; BEGIN { our @ISA = qw( Exporter ); our @EXPORT_OK = qw( send_notice ); require Exporter; } use SYS_mail qw ( send_mail ); sub send_notice { print qq{Hello from AB_prod::send_notice\n}; send_mail(); } 1; #--------------------------------------------------------------------
/usr/web/wonko/test/lib/SYS/SYS_mail.pm #-------------------------------------------------------------------- package SYS_mail; use lib qq{/usr/web/wonko/test/lib/AB}; use strict; use warnings; BEGIN { our @ISA = qw( Exporter ); our @EXPORT_OK = qw( send_mail ); require Exporter; } use AB_prod qw( send_notice ); sub send_mail { print qq{Hello from SYS_mail::send_mail\n}; } 1; #--------------------------------------------------------------------


Tested:

use strict; use warnings; use SYS_mail qw( send_mail ); use AB_prod qw( send_notice ); send_notice(); __END__ output ====== Hello from AB_prod::send_notice Hello from SYS_mail::send_mail

I also tested it with the two use statements inverted. It gave the same output.


Update: It doesn't matter that sub send_mail { ... } hasn't been reached at the point Exporter->import('send_mail') is called, so I removed the stub functions I added just below the BEGIN in SYS_mail. Same idea for AB_prod.

Replies are listed 'Best First'.
Re^2: Namespace and use confusion. "Undefined subroutine errors"
by Wonko the sane (Curate) on May 06, 2005 at 12:01 UTC
    Ah! I understand now. Fantastic answer! Thank you very much.
Re^2: Namespace and use confusion. "Undefined subroutine errors"
by bart (Canon) on May 07, 2005 at 06:50 UTC
    The simple answer is don't do that! Modules calling each other or calling themselves are usually a sign of bad design.
    ... and when that happens, I take it as a sign that you always want both of your source files always to be loaded together. So why put them in separate files? Simply put them together in the same module. Perl does not enforce packages being in the source file as indicated by the package name. It's best to have that package in the source too, as a sanity handle, and to avoid confusion, and otherwise import won't work either; but it's not absolutely required.

    See (the source of) XML::Parser for example, where multiple packages are put into the same module — an example where they might just as well, or maybe even better, have used separate files.