What is the difference between my and local in Perl?

PerlScoping

Perl Problem Overview


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?

Perl Solutions


Solution 1 - Perl

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.

Solution 2 - Perl

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

Solution 3 - Perl

Quoting from Learning Perl:

> But local is misnamed, or at least misleadingly named. Our friend Chip Salzenberg says that if he ever gets a chance to go back in a time machine to 1986 and give Larry one piece of advice, he'd tell Larry to call local by the name "save" instead.[14] That's because local actually will save the given global variable's value away, so it will later automatically be restored to the global variable. (That's right: these so-called "local" variables are actually globals!) This save-and-restore mechanism is the same one we've already seen twice now, in the control variable of a foreach loop, and in the @_ array of subroutine parameters.

So, local saves a global variable's current value and then set it to some form of empty value. You'll often see it used to slurp an entire file, rather than leading just a line:

my $file_content;
{
    local $/;
    open IN, "foo.txt";
    $file_content = <IN>;
} 

Calling local $/ sets the input record separator (the value that Perl stops reading a "line" at) to an empty value, causing the spaceship operator to read the entire file, so it never hits the input record separator.

Solution 4 - Perl

I can’t believe no one has linked to Mark Jason Dominus’ exhaustive treatises on the matter:

Solution 5 - Perl

http://perldoc.perl.org/perlsub.html#Private-Variables-via-my()

> Unlike dynamic variables created by > the local operator, lexical variables > declared with my are totally hidden > from the outside world, including any > called subroutines. This is true if > it's the same subroutine called from > itself or elsewhere--every call gets > its own copy.

http://perldoc.perl.org/perlsub.html#Temporary-Values-via-local()

> A local modifies its listed variables > to be "local" to the enclosing block, > eval, or do FILE --and to any > subroutine called from within that > block. A local just gives temporary > values to global (meaning package) > variables. It does not create a local > variable. This is known as dynamic > scoping. Lexical scoping is done with > my, which works more like C's auto > declarations.

I don't think this is at all unclear, other than to say that by "local to the enclosing block", what it means is that the original value is restored when the block is exited.

Solution 6 - Perl

Well Google really works for you on this one: http://www.perlmonks.org/?node_id=94007

From the link: > Quick summary: 'my' creates a new > variable, 'local' temporarily amends > the value of a variable. > > ie, 'local' temporarily changes the > value of the variable, but only > within the scope it exists in.

Generally use my, it's faster and doesn't do anything kind of weird.

Solution 7 - Perl

From man perlsub:

Unlike dynamic variables created by the local operator, lexical variables declared with my are totally hidden from the outside world, including any called subroutines.

So, oversimplifying, my makes your variable visible only where it's declared. local makes it visible down the call stack too. You will usually want to use my instead of local.

Solution 8 - Perl

Your confusion is understandable. Lexical scoping is fairly easy to understand but dynamic scoping is an unusual concept. The situation is made worse by the names my and local being somewhat inaccurate (or at least unintuitive) for historical reasons.

my declares a lexical variable -- one that is visible from the point of declaration until the end of the enclosing block (or file). It is completely independent from any other variables with the same name in the rest of the program. It is private to that block.

local, on the other hand, declares a temporary change to the value of a global variable. The change ends at the end of the enclosing scope, but the variable -- being global -- is visible anywhere in the program.

As a rule of thumb, use my to declare your own variables and local to control the impact of changes to Perl's built-in variables.

For a more thorough description see Mark Jason Dominus' article Coping with Scoping.

Solution 9 - Perl

local is an older method of localization, from the times when Perl had only dynamic scoping. Lexical scoping is much more natural for the programmer and much safer in many situations. my variables belong to the scope (block, package, or file) in which they are declared.

local variables instead actually belong to a global namespace. If you refer to a variable $x with local, you are actually referring to $main::x, which is a global variable. Contrary to what it's name implies, all local does is push a new value onto a stack of values for $main::x until the end of this block, at which time the old value will be restored. That's a useful feature in and of itself, but it's not a good way to have local variables for a host of reasons (think what happens when you have threads! and think what happens when you call a routine that genuinely wants to use a global that you have localized!). However, it was the only way to have variables that looked like local variables back in the bad old days before Perl 5. We're still stuck with it.

Solution 10 - Perl

"my" variables are visible in the current code block only. "local" variables are also visible where ever they were visible before. For example, if you say "my $x;" and call a sub-function, it cannot see that variable $x. But if you say "local $/;" (to null out the value of the record separator) then you change the way reading from files works in any functions you call.

In practice, you almost always want "my", not "local".

Solution 11 - Perl

Look at the following code and its output to understand the difference.

our $name = "Abhishek";

sub sub1
{
    print "\nName = $name\n";
    local $name = "Abhijeet";

    &sub2;
    &sub3;
}

sub sub2
{
    print "\nName = $name\n";
}

sub sub3
{
    my $name = "Abhinav";
    print "\nName = $name\n";
}


&sub1;

Output is :

Name = Abhishek

Name = Abhijeet

Name = Abhinav

Solution 12 - Perl

dinomite's example of using local to redefine the record delimiter is the only time I have ran across in a lot of perl programming. I live in a niche perl environment [security programming], but it really is a rarely used scope in my experience.

Solution 13 - Perl

&s;

sub s()
{
    local $s="5";
    &b;
    print $s;
}

sub b()
{
    $s++;
}

The above script prints 6.

But if we change local to my it will print 5.

This is the difference. Simple.

Solution 14 - Perl

I think the easiest way to remember it is this way. MY creates a new variable. LOCAL temporarily changes the value of an existing variable.

Solution 15 - Perl

It will differ only when you have a subroutine called within a subroutine, for example:

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

It prints nothing as $x is limited by {} of bar and not visible to called subroutines, for example:

sub foo { print "$x\n"; }

sub bar { local $x; $x = 2; foo(); }
   
bar(); 

It will print 2 as local variables are visible to called subroutines.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrian GView Question on Stackoverflow
Solution 1 - PerlJeremy BourqueView Answer on Stackoverflow
Solution 2 - PerlJ.J.View Answer on Stackoverflow
Solution 3 - PerlDrew StephensView Answer on Stackoverflow
Solution 4 - PerlAristotle PagaltzisView Answer on Stackoverflow
Solution 5 - PerlSteve JessopView Answer on Stackoverflow
Solution 6 - PerldlamblinView Answer on Stackoverflow
Solution 7 - PerlcatfoodView Answer on Stackoverflow
Solution 8 - PerlMichael CarmanView Answer on Stackoverflow
Solution 9 - PerlskiphoppyView Answer on Stackoverflow
Solution 10 - PerlandyView Answer on Stackoverflow
Solution 11 - PerlAbhishek KulkarniView Answer on Stackoverflow
Solution 12 - PerlphreakreView Answer on Stackoverflow
Solution 13 - PerlSaravanarajanView Answer on Stackoverflow
Solution 14 - PerlHawkView Answer on Stackoverflow
Solution 15 - PerlOmtechnologies sView Answer on Stackoverflow