Как я могу локализовать переменные Perl в другом фрейме стека?
Вопрос
У меня есть некоторый автоматически сгенерированный код, который эффективно записывает следующее в нескольких разных местах некоторого кода:
no warnings 'uninitialized';
local %ENV = %ENV;
local $/ = $/;
local @INC = @INC;
local %INC = %INC;
local $_ = $_;
local $| = $|;
local %SIG = %SIG;
use warnings 'uninitialized';
При автоматической генерации кода некоторые утверждают, что нет строгой необходимости в том, чтобы код был "красивым", но я бы хотел перенести это в подпрограмму.Однако это позволило бы локализовать эти переменные в этой подпрограмме.Есть ли способ локализовать эти переменные в вызывающем фрейме стека?
Обновить:В аналогичном ключе было бы неплохо иметь возможность запускать eval в более высоком фрейме стека.Я думаю, что у Python это уже есть.Было бы неплохо, если бы Perl тоже это сделал.
Решение
Возможно, вы можете организовать, чтобы код, использующий эти локальные файлы, генерировался в качестве замыкания?Тогда вы могли бы
sub run_with_env {
my ($sub, @args) = @_;
no warnings 'uninitialized';
local %ENV = %ENV;
local $/ = $/;
local @INC = @INC;
local %INC = %INC;
local $_ = $_;
local $| = $|;
local %SIG = %SIG;
use warnings 'uninitialized';
$sub->(@args);
}
run_with_env(sub {
# do stuff here
});
run_with_env(sub {
# do different stuff here
});
Другие советы
Не уверен, почему QuantumPete отвергают, но, похоже, в этом он прав.Ты не можешь сказать наверняка local
для инициализации переменных в вызывающем блоке.Его функциональность особенная, и инициализация / демонтаж, которые он выполняет, работает только в том блоке, где он был запущен.
Есть несколько экспериментальных модулей, таких как Sub:: Верхний уровень и Разработка::runBlock которые позволяют вам пытаться "обмануть" caller()
для подпрограмм или выполнять "возврат длинных переходов" значений в более высокие кадры стека (соответственно), но ни один из них ничего не делает, чтобы повлиять на то, как local
обрабатывает переменные (я пробовал.:)
Так что на данный момент, похоже, вам действительно придется жить с локальными объявлениями в той области, где они вам нужны.
Я не очень хорошо знаком с Perl, так что простите меня, если это действительно возможно.Но обычно переменные, локальные для фрейма стека, доступны только внутри этого фрейма стека.Вы не можете получить к ним доступ ни с более высокого, ни с более низкого уровня (если только вы не выполните какую-нибудь хакерскую арифметику указателей, но это никогда не гарантирует успеха).К сожалению, вам придется жить с большими блоками объявлений переменных.
Количественный скачок
perldoc перлгутс говорит:
The "Alias" module implements localization of the basic types within
the caller's scope. People who are interested in how to localize
things in the containing scope should take a look there too.
Фу-у-у.Я недостаточно внимательно изучал Alias.pm, чтобы понять, насколько это может быть просто.
В TCL вы можете использовать верхний уровень.Что касается Perl, я не знаю.
Perl имеет Sub:: Верхний уровень