Почему делает эту печать 42:
$answer = 42;
$variable = "answer";
print ${$variable} . "\n";
но это не делает:
my $answer = 42;
my $variable = "answer";
print ${$variable} . "\n";
Только переменные пакета (того типа, который был объявлен в вашем первом примере) могут быть нацелены через символические ссылки. Лексические ( my
) переменные не могут быть, поэтому ваш второй пример не работает.
См. Прекрасную статью Coping with Scoping , чтобы узнать, как работают две отдельные системы переменных в Perl. И посмотрите также отлично Почему глупо использовать переменную имя переменной , почему это глупо. :)
Проблема в том, что вы не можете использовать символьную ссылку для ссылки на лексическую переменную. В обоих примерах $ {$ variable}
ищет $ main :: answer
. В первом случае $ answer
является глобальным пакетом и сокращенно от $ main :: answer
, поэтому ссылка находит его. Во втором случае $ answer
является лексической переменной и не находится ни в одном пакете, поэтому ссылка не может ее найти.
Подробнее см. perlref под заголовком Символические ссылки .
Perl имеет две полностью отдельные, но в значительной степени совместимые системы переменных: переменные пакета, как в первом примере, и лексические переменные, как во втором. Есть несколько вещей, которые каждый может делать, но другой - нет:
Переменные пакета - единственные, которые могут быть:
local
) Лексические переменные только те, которые могут быть закрыты (используются в лексическом закрытии).
Использование strict могло бы помочь, заставив вас объявлять переменные пакета с помощью нашего
, что сделает разницу более ясной.
Есть несколько случаев, когда символические ссылки полезны в Perl, большинство из них сосредоточено вокруг управления таблицей символов (например, написание собственного import
в модуле вместо использования Exporter
, обезьяна- исправление модулей во время выполнения, различные другие задачи метапрограммирования). Все это сложные темы.
Для других задач обычно есть лучший способ сделать это, например, с помощью хэша. Общее практическое правило - всегда запускать с предупреждениями использования; используйте strict;
, если вы не знаете, что нет другого пути, кроме как отключить часть прагмы (например, используя no strict 'refs';
в как можно меньшем объеме).
Символьные ссылки работают только с переменными пакета. Таблица символов не отслеживает лексические переменные (в этом и заключается весь смысл того, что они лексические :)).