Sample code:
m1.pm
my $a;
my $b;
sub init {
$a = shift;
$b = shift;
}
sub printab {
print "a = -$a-\n";
print "b = -$b-\n";
}
1;
m2.pm
my $a;
my $b;
sub init {
$a = shift;
$b = shift;
}
1;
test.pl
use strict;
use warnings;
use m1;
use m2;
init('hello', 'world');
printab();
Run:
$ perl test.pl
a = --
b = --
$
What happens is that the init('hello', 'world')
call is mapped to m2.pm
and initializes the variables ($a
and $b
) there.
This kind of makes sense, but what I do not understand is why those values are not available in test.pl
.
Is there something fundamentally wrong that I am trying to do here? What is the correct way to use two modules with same named subroutines and variables?
How exactly does a Perl
use
work? It would help if someone could contrast it with C's#include
directive.
First, do read perldoc perlmod.
You do not declare a namespace in either module, so everything is in the
main
namespace. Declarepackage m1;
inm1.pm
andpackage m2;
inm2.pm
.At the very least, you should implement an
import
method (or inherit the oneExporter
provides) so that programs that use modules can decide what to import from where.It also seems to me that you are exploring around the edges of OO.
Further:
Avoid using
$a
and$b
as variable names because it is easy to confuse them with the package variables$a
and$b
used bysort
.Don't use lower case module names: They are reserved for pragmata.
A minimal implementation (all in one file for testing convenience) looks like this:
In Perl, the
use
keyword is exactly equivalent to the following:So if you are not defining an import routine in your code (or inheriting from
Exporter
), then your modules are not importing anything intotest.pl
As Sinan caught, you are not declaring a package in your modules, so they are defaulting to the
main
package. In that case, all of your subroutines are inmain
, but the lexical variables (declared withmy
) are only scoped to the file they are declared in.So
m1
definessub init
andsub printab
to which the lexicals$a
and$b
are in scope. But then whentest.pl
loadsm2
, theinit
routine is overwritten with the new definition, which is not closed around the two lexicals anymore. So it is writing to the package variables$main::a
and$main::b
instead of the lexicals whichprintab
is bound to.If you had warnings enabled (which you always should when learning), you would have been warned about the subroutine redefinition.
You should start each of your modules with:
and then end each module with:
This is because when you
use/require
a module, it needs to return a true value at the end so that Perl knows it loaded properly.printab()
is defined in the filem1.pm
and only has access to the$a
and$b
variables that are scoped to that file. The variables$a
and$b
inm2.pm
are scoped to that file, and they are different variables than the$a
and$b
inm1.pm
.init()
sets the variables scoped inm2.pm
(because that's the last place the&init
function was defined) so it is not setting the same variables thatprintab()
will be trying to print.