Local and Global variables in perl
There are two kinds of variables, lexically scoped and globally scoped.
In Perl before version 5, there was only globally scoped. These variables are the package variables. These variables are available everywhere in the program if you use the package prefix.
The local
keyword was introduced to provide a way to alter the value of one of these package global variables inside a limited scope, such as inside one subroutine. It will save the old value on a stack when entering the scope with the local
statement, and upon exiting, it will restore the old value. These are still package globals, which means that they are still available everywhere. If you are inside a scope with a local
variable, and you call a subroutine, that variable is still visible inside that subroutine.
The my
keyword was introduced in version 5, and provides lexically scoped variables. These variables only exist inside the scope where they are declared. This means that if you call a subroutine, that my
variable is not visible. Upon exiting a scope, the my
variables simply go away. You should prefer to use my
variables when possible, because you do not want your variables to be visible inside subroutines that you call. You cannot use these type of variables in the @EXPORT
list because these variables are not visible outside of their scope.
Finally, the our
keyword is a combination of both, in that it gives you a variable that is a package global, but that variable is lexically scoped. This means it will be available anywhere in the program, but at the end of the enclosing block, you cannot refer to that variable any more.
###Example 1:
sub mess_with_foo {
$foo=0;
}
sub myfunc {
my $foo=20;
mess_with_foo();
print $foo;
}
myfunc();
###Example 2:
sub mess_with_foo {
$foo=0;
}
sub myfunc {
local $foo=20;
mess_with_foo();
print $foo;
}
myfunc();
Example 1 prints 20
because mess_with_foo()
could not see my $foo
. It could not change it. my $foo
can only be seen in its scope of myfunc()
.
Example 2 prints 0
because mess_with_foo()
can see my $foo
and change it. local $foo
can be seen in its scope of myfunc()
AND in the scope of any function called from within its scope of myfunc()
.
That's the only difference. Neither my $foo
nor local $foo
will be seen outside of their scope of myfunc()
.
In terms of scoping, there are three kinds of variables in Perl.
Lexical variables are lexically scoped, which means they are only visible in the current lexical scope (basically file or block).
Package variables, on the other hand, can be used using their qualified form (e.g.
$Foo::x
) from anywhere in the interpreter, and they can be used without qualification by any code that shares the variable's package.Certain package variables are visible without qualification anywhere in the interpreter. These include punctuation vars and a few named vars such as
@ARGV
andSTDOUT
. For example,$x
refers to$Foo::x
when in packageFoo
and$Bar::x
when in packageBar
(assuming no lexical var named$x
is in scope), but$_
always refers to$::_
.
Variables are destroyed when they are no longer referenced.
Lexical variables are usually destroyed when the lexical scope is exited.
Package variables are usually destroyed when the program exits.
Here are ways to create variable.
my
andstate
create a lexical variable.our
creates a lexical variable that is aliased to the variable of the same name in the current package. In other words,our $x;
is equivalent tomy \$x = \$Foo::x;
when in packageFoo
.Package variables are created on use.
local
doesn't create any variables. It simply backs up a variable until the current lexical scope is destroyed. It is restored from its backed-up value at that point.
my
does the same thing.
No. local
does not change the scope of a variable. While a lexical variable is only visible in a lexical scope, a localized package variable is still visible across the entire interpreter.
$x = 123;
sub foo { print "$x\n"; }
{ local $x = 456; foo(); } # 456
foo(); # 123
$x = 123;
sub foo { print "$x\n"; }
{ my $x = 456; foo(); } # 123
foo(); # 123
What else for
local
local
is primarily used to approximate the functionality of my
for variables that cannot otherwise be declared lexically.
Historically, that was all variables. Since 5.6, only punctuation variables cannot be declared lexically.
What is "global" variable?
A global variable is a variable that can seen globally.
All package variables can be seen by any code in the interpreter, so they're all global.
Or are they? To see them from other packages, you need to qualify them. Are $x
and $Foo::x
the same variable?
To some, global variables refers to the set of package variables you can use unqualified. It means that package
changes the set of global variables. And since the package
directive is usually used on a file-basis, that means file-level lexicals are also effectively global by this definition. And they are indeed called that sometimes.
But if the package
changes the set of variables that are global, then they're not really global, are they? So think some people, which only consider punctuation variables (e.g. $_
) and the few named variables that can be used unqualified from anywhere (*::STDOUT
) to be global.
In short, it's a pretty useless term.
Is it possible to add the my scoped variables in @EXPORT array and use it in another packages?
No. @EXPORT
is used by Exporter. Exporter would not be able to find anything but package symbols (since files are compiled in fresh lexical scopes), so @EXPORT
must only contain package symbols.
Here's what I found out about variable scopes:
my
declarations are pretty clear and straightforward if used inside blocks. If used in main outside any block, they are a bit different though, meaning that a my
variable declared outside a block is visible even inside functions called from anywhere inside the same file as long as these functions are defined within the same file. If declared inside a block, though, they are not visible to functions even if called from the same block. All my
variables seem to live on the stack. And: you cannot localize them with local
.
our
variables live on the heap. Even if you have a my
variable by the same name, the our variable can still be accessed through ${'var'}
, which looks up a variable of that name in the symbol table and dereferences it. my
variables, on the other hand, have not symbol table entries.
local
variables seem to me like a relic from former Perl versions. They are just re-assignments to global (our
) variables with block scope and resume their former values after the block terminates. I can see no real sense in using them.
My little program below shows all this, and it shows how badly a declared() test is missing, beyond the well-known defined() test, to identify undeclared variables as such.
#!/usr/bin/perl
use strict;
### This is about variable scoping with my, our and local
my $fsv = "file scope"; # visible for all code in this file
our $gsv = "global scope"; # not different from my $fsv, except in packages
our $lsv = "global"; # global scope, but localized in subsequent block
{
my $bsv = "lex scope"; # visible only inside this block, not even in subs called from here
$gsv = "visible everywhere";
local $lsv = "global, but localized val";
print "This is variable \$bsv with value $bsv inside block\n";
print "This is variable \$fsv with value $fsv inside block\n";
print "This is variable \$lsv with value $lsv inside block\n\n";
print_vars("calledfromblock");
}
print_vars("calledfromoutside");
no strict 'vars'; # needed if testing variable for declaredness rather than definedness
if ( defined $bsv ) {
print "\$bsv as defined outside braces: $bsv\n"
} else {
print "\$bsv not defined outside braces\n";
}
print "This is variable \$lsv with value $lsv outside block\n";
# use strict 'vars'; # no strict 'vars' effective even in sub print_vars unless switched back on
sub print_vars
{
my $whence = shift;
my $gsv = "my variable";
no strict 'refs'; # needed to access the global var $gsv using ${'gsv'} despite the my declaration
if ( $whence eq "calledfromblock" ) {
print "\t print_vars called from within the block:\n";
( defined $bsv ) ? print "\$bsv is $bsv inside sub\n" : print "\$bsv not defined inside sub\n";
( defined $fsv ) ? print "\$fsv is $fsv inside sub\n" : print "\$fsv not defined inside sub\n";
( defined ${'gsv'} ) ? print "\$gsv is ${'gsv'} inside sub\n" : print "\$gsv not defined inside sub\n";
( defined ${'lsv'} ) ? print "\$lsv is ${'lsv'} inside sub\n" : print "\$lsv not defined inside sub\n";
} else {
print "\t print_vars called from outside the block:\n";
( defined $bsv ) ? print "\$bsv is $bsv inside sub\n" : print "\$bsv not defined inside sub\n";
( defined $fsv ) ? print "\$fsv is $fsv inside sub\n" : print "\$fsv not defined inside sub\n";
( defined $gsv ) ? print "\$gsv is $gsv inside sub\n" : print "\$gsv not defined inside sub\n";
( defined $lsv ) ? print "\$lsv is $lsv inside sub\n" : print "\$lsv not defined inside sub\n";
}
print "\n";
}