What is the difference between my and local in Perl?

I am seeing both of them used in this script I am trying to debug and the literature is just not clear. Can someone demystify this for me?


The short answer is that my marks a variable as private in a lexical scope, and local marks a variable as private in a dynamic scope.

It's easier to understand my, since that creates a local variable in the usual sense. There is a new variable created and it's accessible only within the enclosing lexical block, which is usually marked by curly braces. There are some exceptions to the curly-brace rule, such as:

foreach my $x (@foo) { print "$x\n"; }

But that's just Perl doing what you mean. Normally you have something like this:

sub Foo {
   my $x = shift;

   print "$x\n";
}

In that case, $x is private to the subroutine and its scope is enclosed by the curly braces. The thing to note, and this is the contrast to local, is that the scope of a my variable is defined with respect to your code as it is written in the file. It's a compile-time phenomenon.

To understand local, you need to think in terms of the calling stack of your program as it is running. When a variable is local, it is redefined from the point at which the local statement executes for everything below that on the stack, until you return back up the stack to the caller of the block containing the local.

This can be confusing at first, so consider the following example.

sub foo { print "$x\n"; }
sub bar { local $x; $x = 2; foo(); }

$x = 1;
foo(); # prints '1'
bar(); # prints '2' because $x was localed in bar
foo(); # prints '1' again because local from foo is no longer in effect

When foo is called the first time, it sees the global value of $x which is 1. When bar is called and local $x runs, that redefines the global $x on the stack. Now when foo is called from bar, it sees the new value of 2 for $x. So far that isn't very special, because the same thing would have happened without the call to local. The magic is that when bar returns we exit the dynamic scope created by local $x and the previous global $x comes back into scope. So for the final call of foo, $x is 1.

You will almost always want to use my, since that gives you the local variable you're looking for. Once in a blue moon, local is really handy to do cool things.


Dynamic Scoping. It is a neat concept. Many people don't use it, or understand it.

Basically think of my as creating and anchoring a variable to one block of {}, A.K.A. scope.

my $foo if (true); # $foo lives and dies within the if statement.

So a my variable is what you are used to. whereas with dynamic scoping $var can be declared anywhere and used anywhere. So with local you basically suspend the use of that global variable, and use a "local value" to work with it. So local creates a temporary scope for a temporary variable.

$var = 4;
print $var, "\n";
&hello;
print $var, "\n";

# subroutines
sub hello {
     local $var = 10;
     print $var, "\n";
     &gogo; # calling subroutine gogo
     print $var, "\n";
}
sub gogo {
     $var ++;
}

This should print:

4
10
11
4