Во-первых, поймите, что есть глобальные (пакетные) переменные и есть лексические переменные. Они могут иметь одинаковое имя. Отныне я буду ссылаться на глобальный $ x по его полному имени $::x
, что сокращенно означает "глобальный пакет $ x main".
Для обратной совместимости, для циклов используйте локализованные глобальные переменные, если вы не укажете обратное, или $ 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()
. Так что я думаю, что документы просто немного небрежны с их терминологией.