Во-первых, поймите, что есть глобальные переменные (в пределах пакета) и есть лексические переменные. Они могут иметь одно и то же имя. С этого момента я буду ссылаться на глобальный пакет $x по его полному имени $::x
, что является сокращением от «основной глобальный пакет $x».
Для обратной совместимости циклы for используют локализованные глобальные переменные, если только вы не укажете иное или $x уже объявлен лексическим (не понял этого). Итак, for $x (2..3) {}
относится к локализованному $::x. for my $x (2..3) {}
относится к лексическому $x. В обоих случаях они находятся внутри цикла, например:
for (2..3) {
my $x = $_;
...
}
За исключением того, что $_ имеет псевдоним $x, а не копируется.
Я считаю, что приведенное выше объясняет, почему при использовании Devel::Peek вы получаете разные скаляры. Поскольку нет эквивалента local()
для лексики, возможно, это объявление нового лексики в лексической панели внутри цикла for, как и в приведенном выше коде.
local($x)
также изменяет базовый SV, потому что он делает что-то вроде:
my $original = $x;
my $new;
*::x = \$new;
...
*::x = \$original;
т.е. создание нового скаляра, вставка его в слот $x в таблице символов, а затем восстановление старого скаляра, когда область действия завершена.
Но это действительно только предположение. Вам придется копаться в коде, чтобы узнать.
Документы, в которых говорится, что лексика «локализована в цикле», не должны пониматься как буквальное local()
. Термин local
сбивает с толку, потому что другие языки и даже программисты Perl используют его взаимозаменяемо для обозначения local()
и "лексической области действия". local()
лучше было бы назвать temp()
. Поэтому я думаю, что документы просто немного небрежны со своей терминологией.
person
Schwern
schedule
12.02.2010