Skip to content

Instantly share code, notes, and snippets.

@klopp
Last active March 26, 2018 13:54
Show Gist options
  • Save klopp/45b005d0ba182d62025e045203cc990b to your computer and use it in GitHub Desktop.
Save klopp/45b005d0ba182d62025e045203cc990b to your computer and use it in GitHub Desktop.
#
# Чем отличаются между собой переменные, объявленные с помощью my, our,local, state?
# Что и почему напечатается, если в качестве XXX подставлять вышеуказанные 4 типа объявления переменных?
#
func() for 1..10;
sub func {
my $var;
$var++;
say "A=$var";
}
# Здесь локальная переменная в своей области видимости. При каждом объявлении она создаётся заново,
# поэтому выведется 10 строк "A=1".
func() for 1..10;
sub func {
our $var;
$var++;
say "A=$var";
}
# Здесь $var - глобальная для пакета переменная. Точнее, алиас для $Package::var. Выведуются строки
# от "A=1" до "A=10". При этом область видимости переменной ограничена функцией func(), поэтому если
# после цикла попробовать написать:
#
# say ++$var;
#
# то получим законную ошибку 'Global symbol "$var" requires explicit package name...'. А вот такая запись:
#
# say ++$main::var;
#
# выведет "11".
func() for 1..10;
sub func {
state $var;
$var++;
say "A=$var";
}
# Статическая переменная. Результат тот же, что и для our.
func() for 1..10;
sub func {
local $var;
$var++;
say "A=$var";
}
# Здесь создаётся локальная копия ранее объявленой переменной, обладающая всеми её свойствами (*). Поскольку
# до того переменной $var не существовало, получим ошибку 'Global symbol "$var" requires explicit package name...'.
#
# (*) Никогда не задумывался как именно это устроено на низком уровне. Видится примерно такая картина: переменная в
# данном случае - не одно значение, а стек значений. В каждый момент времени используется то, что на верхушке.
# Local добавляет новое значение в этот стек (копируя текущую вершину). А после выхода из области видимости
# верхушка выталкивается и используется предыдущее значение.
#
# А как вы объясните странные результаты выдачи в таком случае?
#
sub func {
my $var if 0;
$var++;
say "A=$var";
}
# Создание локальной переменной, к которой позже идёт обращение, находится в левой части выражения, значение
# которого ложно. Следовательно, операция не сможет быть выполнена, и такая запись запрещена (была бы
# разрешена - наверное, приводила бы к UB).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment