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?
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
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
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.
I can’t believe no one has linked to Mark Jason Dominus’ exhaustive treatises on the matter:
And afterwards, if you want to know what
local
is good for after all,
Seven Useful Uses oflocal
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.
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.
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
.
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.
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.
"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".
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
&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.
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.
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.
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.
#!/usr/bin/perl
sub foo { print ", x is $x\n"; }
sub testdefault { $x++; foo(); } # prints 2
sub testmy { my $x; $x++; foo(); } # prints 1
sub testlocal { local $x = 2; foo(); } # prints 2. new set mandatory
print "Default, everything is global";
$x = 1;
testdefault();
print "My does not affect function calls outside";
$x = 1;
testmy();
print "local is everything after this but initializes a new";
$x = 1;
testlocal();
As mentioned in testlocal comment, declaring "local $x;" means that $x is now undef
© 2022 - 2024 — McMap. All rights reserved.