package variable scope in module subroutine
As you found out, when you use my
, you are creating a locally scoped non-package variable. To create a package variable, you use our
and not my
:
my $foo = "this is a locally scoped, non-package variable";
our $bar = "This is a package variable that's visible in the entire package";
Even better:
{
my $foo = "This variable is only available in this block";
our $bar = "This variable is available in the whole package":
}
print "$foo\n"; #Whoops! Undefined variable
print "$bar\n"; #Bar is still defined even out of the block
When you don't put use strict
in your program, all variables defined are package variables. That's why when you don't put it, it works the way you think it should and putting it in breaks your program.
However, as you can see in the following example, using our
will solve your dilemma:
File Local/Foo.pm
#! /usr/local/bin perl
package Local::Foo;
use strict;
use warnings;
use feature qw(say);
use Exporter 'import';
our @EXPORT = qw(testme);
our $bar = "This is the package's bar value!";
sub testme {
# $foo is a locally scoped, non-package variable. It's undefined and an error
say qq(The value of \$main::foo is "$main::foo");
# $bar is defined in package main::, and will print out
say qq(The value of \$main::bar is "$main::bar");
# These both refer to $Local::Foo::bar
say qq(The value of \$Local::Foo::bar is "$Local::Foo::bar");
say qq(The value of bar is "$bar");
}
1;
File test.pl
#! /usr/local/bin perl
use strict;
use warnings;
use feature qw(say);
use Local::Foo;
my $foo = "This is foo";
our $bar = "This is bar";
testme;
say "";
$Local::Foo::bar = "This is the NEW value for the package's bar";
testme
And, the output is:
Use of uninitialized value $foo in concatenation (.) or string at Local/Foo.pm line 14.
The value of $main::foo is ""
The value of $main::bar is "This is bar"
The value of $Local::Foo::bar is "This is the package's bar value!"
The value of bar is "This is the package's bar value!"
Use of uninitialized value $foo in concatenation (.) or string at Local/Foo.pm line 14.
The value of $main::foo is ""
The value of $main::bar is "This is bar"
The value of $Local::Foo::bar is "This is the NEW value for the package's bar"
The value of bar is "This is the NEW value for the package's bar"
The error message you're getting is the result of $foo
being a local variable, and thus isn't visible inside the package. Meanwhile, $bar
is a package variable and is visible.
Sometimes, it can be a bit tricky:
if ($bar -eq "one") {
my $foo = 1;
}
else {
my $foo = 2;
}
print "Foo = $foo\n";
That doesn't work because $foo
only bas a value inside the if
block. You have to do this:
my $foo;
if ($bar -eq "one") {
$foo = 1;
}
else {
$foo = 2;
}
print "Foo = $foo\n"; #This works!
Yes, it can be a bit to get your head wrapped around it initially, but the use of use strict;
and use warnings;
is now de rigueur and for good reasons. The use of use strict;
and use warnings;
probably has eliminated 90% of the mistakes people make in Perl. You can't make a mistake of setting the value of $foo
in one part of the program, and attempting to use $Foo
in another. It's one of the things I really miss in Python.
Admin
Updated on July 09, 2022Comments
-
Admin almost 2 years
How do I change the value of a variable in the package used by a module so that subroutines in that module can use it?
Here's my test case:
testmodule.pm:
package testmodule; use strict; use warnings; require Exporter; our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); @ISA = qw(Exporter); @EXPORT = qw(testsub); my $greeting = "hello testmodule"; my $var2; sub testsub { printf "__PACKAGE__: %s\n", __PACKAGE__; printf "\$main::greeting: %s\n", $main::greeting; printf "\$greeting: %s\n", $greeting; printf "\$testmodule::greeting: %s\n", $testmodule::greeting; printf "\$var2: %s\n", $var2; } # End testsub 1;
testscript.pl:
#!/usr/bin/perl -w use strict; use warnings; use testmodule; our $greeting = "hello main"; my $var2 = "my var2 in testscript"; $testmodule::greeting = "hello testmodule from testscript"; $testmodule::var2 = "hello var2 from testscript"; testsub();
output:
Name "testmodule::var2" used only once: possible typo at ./testscript.pl line 11. __PACKAGE__: testmodule $main::greeting: hello main $greeting: hello testmodule $testmodule::greeting: hello testmodule from testscript Use of uninitialized value $var2 in printf at testmodule.pm line 20. $var2:
I expected
$greeting
and$testmodule::greeting
to be the same since the package of the subroutine istestmodule
.I guess this has something to do with the way
use
d modules areeval
d as if in aBEGIN
block, but I'd like to understand it better.I was hoping to set the value of the variable from the main script and use it in the module's subroutine without using the fully-qualified name of the variable.
-
yonetpkbji over 10 yearsExcellent explanation and examples, solved and understood all my problems as a result. thanks
-
ShooShoSha over 4 yearsSearched for answer to accessing module variables, learned more about variable scoping. Good answer +1