В Perl существуют три основных типа объявления переменных: my, our и state.
sub example_state { state $counter = 0; $counter++; return $counter; } for (1..3) { print example_state(), " "; # Выведет 1, затем 2, затем 3 }
Где правильно использовать:
my — почти всегда предпочтительный выбор для переменных, если нет причины для глобального доступа.our — для экспорта переменных между модулями, когда требуется совместное использование.state — в случае, если переменная должна "запоминать" значение между вызовами функции (например, счетчик вызовов).Может ли переменная, объявленная с помощью our, быть закрыта (captured) в замыкании наравне с my?
Обычно отвечают "да, это удобно", но это не так. our переменная — глобальна для пакета, и замыкание по сути занимается не связыванием ее значения в момент создания closure, а обращением через глобальное имя. Поэтому ее "значение" может измениться снаружи closure и затронет все замыкания!
our $x = 10; my $closure = sub { return $x; }; $x = 42; print $closure->(); # Вернет 42, а не 10
История
В крупном скрипте для парсинга логов переменные объявлялись через our для "удобного обращения" из разных функций модуля. В результате изменение этих переменных в одной функции приводило к неожиданному поведению в другой, ломая параллельную обработку логов.
История
Использование my для переменных, значение которых требовалось сохранять между вызовами функции (например, счетчик внутри рекурсивного обхода), приводило к сбросу значения на каждом вызове, что вызывало некорректную логику обхода. Замена на state исправила ситуацию.
История
Некорректное использование our в импортируемом модуле (export переменных не через Exporter) вызвало коллизию имен при подключении двух разных модулей, использующих одинаковое имя переменной. В итоге данные "перепрыгивали" из одного контекста в другой.