Как я могу локализовать переменные 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 тоже.
6 ответов
Возможно, вы можете организовать код, который использует эти локальные объекты, как замыкание? Тогда вы могли бы
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::Uplevel и Devel::RunBlock, которые позволяют вам пытаться "обмануть" caller()
для подпрограмм или для "длинного прыжкового возврата" значений в более высокие кадры стека (соответственно), но ни один из них не влияет на то, как local
относится к переменным (я пробовал.:)
Так что сейчас, похоже, вам придется жить с местными объявлениями в той области, где они вам нужны.
Perldoc Perlguts говорит:
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.
FWIW. Я недостаточно внимательно посмотрел на Alias.pm, чтобы понять, насколько это легко.
Я не очень знаком с Perl, так что простите, если это возможно. Но обычно переменные, локальные для стекового фрейма, доступны только внутри этого стекового фрейма. Вы не можете получить к ним доступ ни с более высокого, ни с более низкого уровня (если только вы не выполните какую-то хакерскую арифметику с указателями, но это никогда не гарантирует успеха). К сожалению, вам придется смириться с большими блоками объявлений переменных.
QuantumPete
В TCL вы можете использовать Uplevel. Что касается Perl, я не знаю.