Modules using each other

P

Poker Man

Hello,

I have run into a weird sticky situation which I hope is something is
so blaringly obvious that I can resolve this quickly.

I put all my re-used subroutines into two PM modules :

MYoutput.pm
MYdatabase.pm

In each module I use

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw( ..list every function here..)

Actually everything has been great. I write many different Perl
scripts and each one has the lines "use MYoutput & use
MYdatabase".

As well, the MYdatabase module has in it, "use MYoutput" so that any
errors get reported properly through the output functions that I wrote.

I thought I was doing everything correctly until just recently.

Within the MYoutput module I decided to call some database related
functions and therefore added "use MYdatabase" to the top of that
module, and that's where things fell apart.

The output module was unable to find the newly included function unless
I prefaced it with "&MYdatabase::" and even then it acted funny.

So I am wondering, cannot two PM's use each other? Or is that some
sort of Perl Paradox?

I guess I could put all my subroutines in just one PM module, but
figured I should try here first.

Thanks
 
C

Ch Lamprecht

Poker said:
Hello,

I have run into a weird sticky situation which I hope is something is
so blaringly obvious that I can resolve this quickly.

I put all my re-used subroutines into two PM modules :

MYoutput.pm
MYdatabase.pm

In each module I use

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw( ..list every function here..)

Hi,

you don't add complete code, so I will:

file mod1.pm:

package mod1;

require Exporter;
use vars qw(@ISA @EXPORT);
use mod2;
@ISA = qw(Exporter);
@EXPORT = qw( out_1 );

sub out_1{
print "$_[0] printed from mod1\n";
out_2($_[0]);
}

file mod2.pm:

package mod2;
require Exporter;
use vars qw(@ISA @EXPORT);
use mod1;
@ISA = qw(Exporter);
@EXPORT = qw( out_2 );

sub out_2{
print "$_[0] printed from mod2\n"
}


file test.pl:

use strict;
use warnings;
use mod1;
use mod2;

out_2("Hello, Poker Man");
out_1("Hello, Poker Man");



test.pl prints:

Hello, Poker Man printed from mod2
Hello, Poker Man printed from mod1
Hello, Poker Man printed from mod2


HTH Christoph
 
C

Ch Lamprecht

Ch said:
Hi,

you don't add complete code, so I will:
I added some lines, and I think I get your point now:
file mod1.pm:
package mod1;
require Exporter;
use vars qw(@ISA @EXPORT);
use mod2;
@ISA = qw(Exporter);
@EXPORT = qw( out_1 out_3);

sub out_1{
print "$_[0] printed from mod1\n";
out_2($_[0]);
}
sub out_3{
print "$_[0] printed from mod1\n";
}
1;
file mod2.pm:
package mod2;
use strict ;
use warnings;
require Exporter;
use vars qw(@ISA @EXPORT);
use mod1;
@ISA = qw(Exporter);
@EXPORT = qw( out_2 );

sub out_2{
print "$_[0] printed from mod2\n";
out_3($_[0]);
}
1;
file test.pl:
use strict;
use warnings;
use mod1;
use mod2;

out_1("Hello, Poker Man");

__END__

test.pl now prints:

Hello, Poker Man printed from mod1
Hello, Poker Man printed from mod2
Undefined subroutine &mod2::eek:ut_3 called at mod2.pm line 12.

Mmh,
Christoph
 
P

Poker Man

Yeah, sorry I didn't place my code there, both PM modules combined are
over 1500 lines. But it seems you've duplicated my problem so I was
hoping that this was me doing a well known mistake.

Any thoughts as to what it could be? Am thinking at this point it's
time for me to just combine both PM's into one, but I so don't want to.
 
P

Peter Scott

Yeah, sorry I didn't place my code there, both PM modules combined are
over 1500 lines. But it seems you've duplicated my problem so I was
hoping that this was me doing a well known mistake.

Any thoughts as to what it could be? Am thinking at this point it's
time for me to just combine both PM's into one, but I so don't want to.

This is a known problem with cyclic module dependencies. The problem is
that %INC has already been marked for mod1 the moment it was first used,
so the use mod1 statement in mod2 does not require mod1 again. But
out_3() in mod1 has not been compiled at the point it encountered the use
mod2 line and started compiling mod2.

The solution is to redesign your modules and the order of subroutine
definitions and use statements. Preferably, avoid cyclic dependencies
altogether.
 
A

A. Sinan Unur

....


This is a known problem with cyclic module dependencies.
....

The solution is to redesign your modules

And that redesign should result in more modules, not fewer, as you
factor out common functionality. You should not regard a module as a
storage shed where you toss in everything you have in the hope of using
them at some point. Divide cleanly across functionality.

Sinan
 
C

Ch Lamprecht

Poker said:
Ch Lamprecht wrote:




Yeah, sorry I didn't place my code there, both PM modules combined are
over 1500 lines. But it seems you've duplicated my problem so I was
hoping that this was me doing a well known mistake.

Any thoughts as to what it could be? Am thinking at this point it's
time for me to just combine both PM's into one, but I so don't want to.

Hi,
as pointed out by others in the thread, best way would be redesigning
your modules.
Nevertheless... as a quick and dirty workaround to make your application
run you could try to put the use statements into a string eval:

file Mod1.pm:

package Mod1;
require Exporter;
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw( out_1 out_3 check_mod1);
eval ('use Mod2 qw(out_2)') ;
sub out_1{
print "$_[0] printed from Mod1\n";
out_2($_[0]);
}
sub out_3{
print "$_[0] printed from Mod1\n";
}
sub check_mod1{
return (exists &$_)? 1:0 ;
}
1;

file Mod2.pm :

package Mod2;
use strict ;
use warnings;
require Exporter;
use vars qw(@ISA @EXPORT_OK);
@ISA = qw(Exporter);
@EXPORT_OK = qw( out_2 check_mod2);
eval ('use Mod1 qw(out_1 out_3)');

sub out_2{
print "$_[0] printed from Mod2\n";
out_3($_[0]);
}
sub check_mod2{
return (exists &$_)? 1:0 ;
}
1;

file test.pl:

use Data::Dumper;
use strict;
use warnings;
use Mod1 qw(out_1 out_3 check_mod1);
use Mod2 qw(out_2 check_mod2);
for (qw(out_1 out_2 out_3)){
print "$_ exists in main\n" if exists &$_;
print "$_ exists in mod1\n" if check_mod1($_);
print "$_ exists in mod2\n" if check_mod2($_);
print "\n";
}
out_1("Hello, Poker Man");
out_3("Hello, Poker Man");

__END__


test.pl prints:

out_1 exists in main
out_1 exists in mod1
out_1 exists in mod2

out_2 exists in main
out_2 exists in mod1
out_2 exists in mod2

out_3 exists in main
out_3 exists in mod1
out_3 exists in mod2

Hello, Poker Man printed from Mod1
Hello, Poker Man printed from Mod2
Hello, Poker Man printed from Mod1
Hello, Poker Man printed from Mod1

HTH, Christoph
 
P

Poker Man

And that redesign should result in more modules, not fewer, as you
factor out common functionality.

Just wanted to thank everyone for their notes. Am a little put off
that I have to now design my PM's based on usage and order, etc. Was
really thinking they could be used as just libraries, or as somebody pu
tit best "storage sheds", but hey, those are the breaks. Guess this
has to do with the way Perl compiles? Just a guess, what do I know?

Anyway, thanks again, at least I can move on from here, that's what
really counts.
 
A

A. Sinan Unur

Just wanted to thank everyone for their notes. Am a little put off
that I have to now design my PM's based on usage and order, etc.

Circular dependencies are circular dependencies. You would have had a
similar problem in C given a single-pass linker (i.e. you would have had
to link some object or library files twice).

Your signature separator is incorrect: It should be
dash-dash-space-newline. Yours is missing the space.
 
P

Poker Man

A. Sinan Unur said:
Your signature separator is incorrect: It should be
dash-dash-space-newline. Yours is missing the space.

Sorry about that, am using Google Groups and doing it manually. Hate
Google Groups, but am in Starbucks, and can't log into my ISP's
newserver from here.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,266
Messages
2,571,077
Members
48,772
Latest member
Backspace Studios

Latest Threads

Top