First, realize that there are global (package scoped) variables and there are lexical variables. They can have the same name. From now own I'll refer to the global $x by its fully qualified name $::x
which shorthand for "the global $x package main".
For backwards compatibility, for loops use localized globals unless you tell it otherwise, or $x has already been declared lexical (didn't realize that). So for $x (2..3) {}
refers to a localized $::x. for my $x (2..3) {}
refers to a lexical $x. In both cases they're scoped inside the loop, sort of like:
for (2..3) {
my $x = $_;
...
}
Except $_ is aliased to $x, not copied.
I believe the above explains why you get different scalars when you use Devel::Peek. Since there is no equivalent of local()
for a lexical it is probably declaring a new lexical on the lexical pad inside the for loop, just like the code above.
local($x)
also changes the underlying SV because it is doing something like:
my $original = $x;
my $new;
*::x = \$new;
...
*::x = \$original;
ie. making a new scalar, plugging it into the $x slot on the symbol table, and then restoring the old scalar when when the scope is done.
But that's really just supposition. You'd have to dig into the code to find out.
The docs saying that a lexical is "localized to the loop" should not be taken to mean the literal local()
. The term local
is confusing because other languages, and even Perl programmers, use it interchangeably to mean local()
and "lexical scope". local()
would probably better be termed temp()
. So I think the docs are just being a little sloppy with their terminology there.