19

I am having few doubts about the local/our scope in Perl. I read a lot of documentation, but I am still in confusion is there. Following are the confusions

  1. What is local scope?

    what I read is -> local copies the value of global variable, change the value, user will use it and outside the block it will retain the global value

    Confusion -> my does the same thing. Only benefit I see is that some variables like $package::var cannot be declared with my scope but can be declared with local scope. What else for local

  2. What is "global" variable?

What is read is -> Its scope is within the package. Basically we put the global variable in @EXPORT array and use it or append the namespace with it to use in other packages.

doubt -> Again if we declare variable with my scope in main only then we can access the variable throughout the package. Is that right? Is it possible to add the my scoped variables in @EXPORT array and use it in another packages?

I think global variables are declared with our keyword. Is there any other way to do so?

This question may look repetitive, but I am confused.

Arka Mukherjee
  • 1,634
  • 8
  • 19
Nitesh
  • 1,715
  • 3
  • 27
  • 47
  • Kevin : How to highlight that. like my our all keyboards are highlighes – Nitesh Sep 30 '13 at 17:27
  • 1
    Put single quote marks (`) around the word to highlight. – Kevin Panko Sep 30 '13 at 17:28
  • 2
    http://stackoverflow.com/questions/845060/what-is-the-difference-between-my-and-our-in-perl – Kevin Panko Sep 30 '13 at 17:47
  • 4
    Questions about Perl variable scoping may be a bit repetitive, but it's very important. Perl variables are extremely difficult to understand. Much of it has to do with Perl's long history as it went from a mere hackish replacement for `awk` and `sh` and turned into a full object oriented language. At one time, all variables were package variables, and `local` was how you limited their scope. Now, we have three different variable types (don't forget `state`!), and this `local` function that doesn't really make local variables. – David W. Mar 05 '14 at 14:51

4 Answers4

23

In terms of scoping, there are two kinds of variables in Perl.

  • Lexical variables are lexically scoped, which means they are only visible in the current lexical scope.
  • Package variables are globally scoped, which means they are visible by all code in the interpreter.

Here are ways to create variable.

  • my creates 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 $foo; is the same as alias my $foo = $The::Current::Package::foo;.
  • Global variables are created on use.

local doesn't create any variables. It simply backs up a variable until the current lexical scope is destroyed.


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 global 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 variable that can seen globally, i.e. by any code in the interpreter.


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 global symbols (since files are compiled in fresh lexical scopes), so @EXPORT must only contain global symbols.

ikegami
  • 322,729
  • 15
  • 228
  • 466
  • 'ikegami' : Basically 'local' and 'my' are same except for scope. 'my' cannot be accessed as you shown in the foo() but local works there. Are there any real practical scenarios where we use 'local' – Nitesh Sep 30 '13 at 17:46
  • why local is called dynamic scoping – Nitesh Sep 30 '13 at 17:47
  • 1
    No, that's completely wrong. Only symbols have scopes, and there's no such thing as a local var. As I already said, `local $_;`, cause you can't do `my $_;` – ikegami Sep 30 '13 at 17:49
  • Cause that's a name for what it does if you ignore the fact that variable doesn't stop existing after `local`'s scope is exited. – ikegami Sep 30 '13 at 17:53
  • 1
    @Nitesh There are many real, practical scenarios where you can use `local`. A common example is [reading a file into a scalar](http://www.perlmonks.org/?node_id=287647). – ThisSuitIsBlackNot Sep 30 '13 at 17:57
6

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.

Kevin Panko
  • 7,844
  • 19
  • 46
  • 58
  • why local is called dynamic scoping – Nitesh Sep 30 '13 at 17:48
  • 2
    The scope of a `local` variable depends on what happens at run-time. The variable's scope begins at the line with `local` and ends at the end of the enclosing block, but that variable's scope also includes all of the subroutines that are called in between. To contrast, a `my` variable has a static scope, because it does not change based on what happens at run-time. – Kevin Panko Sep 30 '13 at 17:52
  • please add example – Alex Oct 16 '16 at 21:28
6

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";
 }
Anthony Geoghegan
  • 10,032
  • 4
  • 42
  • 50
striver
  • 61
  • 1
  • 1
  • 1
    That was a useful answer with nice explanatory code. I've upvoted and edited it to remove line numbers from the program code, fix mis-spellings, add add code formatting for Perl keywords. – Anthony Geoghegan Nov 19 '19 at 12:05
5

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().

cincodenada
  • 2,492
  • 17
  • 35