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. Declare package m1;
in m1.pm
and package m2;
in m2.pm
.
At the very least, you should implement an import
method (or inherit the one Exporter
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:
A minimal implementation (all in one file for testing convenience) looks like this:
package My::M1;
use strict; use warnings;
sub new { my $class = shift; bless { @_ } => $class }
sub a {
my $self = shift;
my ($v) = @_;
$self->{a} = $v if @_;
return $self->{a};
}
sub b {
my $self = shift;
my ($v) = @_;
$self->{b} = $v if @_;
return $self->{b};
}
package My::M2;
use strict; use warnings;
use base 'My::M1';
sub printtab {
my $self = shift;
for my $x (qw(a b)) {
printf "%s = -%s-\n", $x, $self->$x;
}
}
package main;
my $m = My::M2->new(a => 'hello', 'b' => 'world');
$m->printtab;
In Perl, the use
keyword is exactly equivalent to the following:
use Mymodule;
#is the same as
BEGIN {
require Mymodule;
Mymodule->import();
}
So if you are not defining an import routine in your code (or inheriting from Exporter
), then your modules are not importing anything into test.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 in main
, but the lexical variables (declared with my
) are only scoped to the file they are declared in.
So m1
defines sub init
and sub printab
to which the lexicals $a
and $b
are in scope. But then when test.pl
loads m2
, the init
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 which printab
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:
package Some::Package::Name;
use warnings;
use strict;
and then end each module with:
1;
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 file m1.pm
and only has access to the $a
and $b
variables that are scoped to that file. The variables $a
and $b
in m2.pm
are scoped to that file, and they are different variables than the $a
and $b
in m1.pm
.
init()
sets the variables scoped in m2.pm
(because that's the last place the &init
function was defined) so it is not setting the same variables that printab()
will be trying to print.