Perl имеет две отдельные, но в значительной степени совместимые переменные системы.
Переменные пакета, которые являются либо полностью квалифицированными именами $Some::Package::variable
, либо лексическими именами, объявленными с our
.Переменные пакета находятся в таблице символов, являются глобальными для всей программы, могут быть целью символической разыменования и могут иметь динамическую область видимости с local
.
Лексическими переменными, объявленными с my
составляют другую переменную систему.Эти переменные не живут в пакете или таблице символов (вместо этого они живут в лексической панели, которая прикреплена к области видимости).Эти переменные не являются глобальными, не могут иметь символическую ссылку и не могут иметь динамическую область видимости.Вот почему вы не можете использовать $$varname
и ожидать, что он найдет лексическую переменную.
У вас есть несколько способов решить эту проблему:
use packageпеременные, либо полностью квалифицированные имена, либо объявленные с помощью our
, строго запрещают использование и используют символические ссылки:
our $x = 1;
our $y = 'x';
say $x; # 1
$$y = 5; # this line is an error if `use strict` is loaded
say $x; # 5
используют переменные пакета и обходят таблицу символов:
$main::x = 1;
my $y = 'x';
${$main::{$y}} = 5; # ok with `use strict`
say $main::x; # 5
лучший способ - использовать хеш (что и делают два вышеупомянутых примера за кулисами, поскольку сама таблица символов является хешем)
my %data = (x => 1);
my $y = 'x';
$data{$y} = 5;
say $data{x}; # 5
Опасность символьных ссылок заключается в том, что зачастую слишком просто превратить вашу программу в код спагетти или перезаписать переменные, которые вы не собирались делать.Используя явный хеш, вы ограничиваете магию того, что вы делаете, четко определенной и ограниченной областью действия.Сам хеш может быть лексическим, что позволяет правильно собирать мусор ваших переменных.