Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Sharing variables and subroutines between modules: unexpected warnings and errors.

by dimar (Curate)
on Mar 15, 2005 at 19:16 UTC ( [id://439722]=perlquestion: print w/replies, xml ) Need Help??

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

Background

Three test perl scripts:
tryStuffAlpha.pm : a small test "hello-world" module that is part of a pair.
tryStuffBeta.pm : a small test "hello-world" module that is part of a pair.
tryStuff_Caller.pl : a script that uses two the test modules.
(NOTE: Alpha and Beta are essentially identical modules, just 'mirror images' of each other with different names.)
Goals:
The Alpha and Beta modules need the capability to share one or more scalar variables with each other.
The Alpha and Beta modules need the capability to share subroutines with each other.
The Caller script needs the capability to access all the common and combined functionality of the Alpha and Beta modules.
All three scripts are supposed to demonstrate the bare-minimum amount of code necessary to reach the desired goals in perl.

Original Source Code

The source code of the three scripts is as follows.

tryStuffAlpha

### begin_: tryStuffAlpha.pm package tryStuffAlpha; use strict; use warnings; use Exporter; use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION); use vars qw( $PermaLink $OppositePermaLink ); $VERSION = 1.00; # Or higher @ISA = qw(Exporter); use tryStuffBeta; ### begin_: init vars $PermaLink = "PERMALINK-ALPHA\n"; $OppositePermaLink = "AOppositeLink=" .$tryStuffBeta::Permalink." +\n"; ### begin_: subroutines push @EXPORT_OK, qw( SayHello ); sub SayHello { my $strOut; $strOut = "Alpha Says Hello World! \n"; return $strOut; }###end_sub push @EXPORT_OK, qw( SayOpposite ); sub SayOpposite { my $strOut; $strOut = "Say Opposite Alpha =".tryStuffBeta::SayHello(); return $strOut; }###end_sub ### begin_: end perl 1; __END__

tryStuffBeta

### begin_: tryStuffBeta.pm package tryStuffBeta; use strict; use warnings; use Exporter; use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION); use vars qw( $PermaLink $OppositePermaLink ); $VERSION = 1.00; # Or higher @ISA = qw(Exporter); use tryStuffAlpha; ### begin_: init vars $PermaLink = "PERMALINK-BETA\n"; $OppositePermaLink = "BOppositeLink=" .$tryStuffAlpha::Permalink. +"\n"; ### begin_: subroutines push @EXPORT_OK, qw( SayHello ); sub SayHello { my $strOut; $strOut = "Beta Says Hello World! \n"; return $strOut; }###end_sub push @EXPORT_OK, qw( SayOpposite ); sub SayOpposite { my $strOut; $strOut = "Say Opposite Beta =".tryStuffAlpha::SayHello(); return $strOut; }###end_sub ### begin_: end perl 1; __END__

tryStuff_Caller

### begin_: tryStuff_Caller.pl use strict; use warnings; use tryStuffAlpha; ### <a href="./tryStuffAlpha.pm" /> use tryStuffBeta; ### <a href="./tryStuffBeta.pm" /> ### begin_: main print "1: ". tryStuffAlpha::SayHello(); ### OK print "2: ". tryStuffBeta::SayHello(); ### OK print "3: ". tryStuffAlpha::SayOpposite(); ### OK print "4: ". tryStuffBeta::SayOpposite(); ### OK print "5: ". $tryStuffAlpha::PermaLink; ### OK print "6: ". $tryStuffBeta::PermaLink; ### OK print "7: ". $tryStuffAlpha::OppositePermaLink; ### FAILS print "8: ". $tryStuffBeta::OppositePermaLink; ### FAILS

Problem

The three scripts are not behaving as expected and/or desired:
Run Result Alpha : (unexpected1) warns about uninitialized value, apparently b/c it does not "see" the scalar from the other module.
Run Result Alpha : (unexpected2) warns about redefined subroutines, not sure why.
Run Result Beta : (unexpected3) same problems as Alpha.
Run Result Caller : (expected but not wanted) warns about uninitialized value, apparently caused by unexpected1.
Run Result Caller : (wanted but not explained) successfully outputs the result of all subroutines as expected, even though there is the 'redefined' warning when Alpha and Beta are run individually.
### Run Result Alpha (tryStuffAlpha.pm run all by itself) Use of uninitialized value ... at tryStuffAlpha.pm line 29. Use of uninitialized value ... at tryStuffBeta.pm line 29. Subroutine SayHello redefined ... tryStuffAlpha.pm line 35. Subroutine SayOpposite redefined ... tryStuffAlpha.pm line 42. Use of uninitialized value ... tryStuffAlpha.pm line 29. ### Run Result Beta (tryStuffBeta.pm run all by itself) Use of uninitialized value ... at tryStuffBeta.pm line 29. Use of uninitialized value ... at tryStuffAlpha.pm line 29. Subroutine SayHello redefined ... tryStuffBeta.pm line 35. Subroutine SayOpposite redefined ... tryStuffBeta.pm line 42. Use of uninitialized value ... tryStuffBeta.pm line 29. ### Run Result Caller (tryStuff_Caller.pm run all by itself) Use of uninitialized value in concatenation (.) or string at tryStuffB +eta.pm line 29. Use of uninitialized value in concatenation (.) or string at tryStuffA +lpha.pm line 29. 1: Alpha Says Hello World! 2: Beta Says Hello World! 3: Say Opposite Alpha =Beta Says Hello World! 4: Say Opposite Beta =Alpha Says Hello World! 5: PERMALINK-ALPHA 6: PERMALINK-BETA 7: AOppositeLink= 8: BOppositeLink=

Questions

The main question is what is the proper syntax to get the two modules Alpha and Beta to share their scalar variable with each other? What is the reason for the subroutine 'redefined' warnings? What is the way to make all the 'redefined' warnings go away when the modules are run separately? This is apparently a very simple problem of variable scope, any clarification on this issue is welcome.

=oQDlNWYsBHI5JXZ2VGIulGIlJXYgQkUPxEIlhGdgY2bgMXZ5VGIlhGV

Replies are listed 'Best First'.
Re: Sharing variables and subroutines between modules: unexpected warnings and errors.
by Tanktalus (Canon) on Mar 15, 2005 at 20:14 UTC

    It's called a "race condition". I've seen it, but I try really hard to avoid it. Not always easy to do.

    X uses Y, Y uses X. So let's go down the compiler's path for this. During the compilation of X, we see this statement "use Y;". So, we stop compiling X, load Y, and compile it. During that, we see the statement to "use X;". We stop and ... no, we see that X is already loaded. So we call X->import(), and continue. We finish compiling Y, including executing any of its global statements, and then go back to X and continue.

    The solutions include:

    • Breaking this relationship in one direction. Allow X to use Y, but not the other way around.
    • Put all variables into functions. You'll need to watch out for infinite recursion if you leave your definitions as-is, I think. But I didn't fully grasp the code, so you may be ok.
    • Put all common code into a common parent class. This is like the first option: breaking the relationship, except this does it in both directions. X uses W, and Y uses W, and W doesn't care about X nor Y.
    • Put everything in the same compilation unit (module). :-)
    • Others? I'm sure there are others. Regardless of what they are, they will usually be a redesign of some magnitude, large or small.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://439722]
Approved by moot
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (5)
As of 2024-04-18 01:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found