Подтвердить что ты не робот

Как я могу локализовать переменные 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 тоже.

4b9b3361

Ответ 1

Возможно, вы можете организовать код, который использует эти локали, которые будут созданы как закрытие? Тогда вы могли бы

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
});

Ответ 2

Не уверен, почему QuantumPete сокращается, он, похоже, прав на этом. Вы не можете указать local инициализировать переменные в вызывающем блоке. Его функциональность является особенной, а инициализация/отрыв, который он выполняет, работает только на блоке, где он был запущен.

Есть несколько экспериментальных модулей, таких как Sub:: Uvelvel и Devel:: RunBlock, которые позволяют вам пытаться "обмануть" caller() для подпрограмм или выполнить "возврат с длинным переходом" к более высоким кадрам стека (соответственно), но ни один из них не влияет на то, как local обрабатывает переменные (я пытался.:)

Итак, на самом деле, похоже, вам придется жить с локальными объявлениями в области, в которой они вам нужны.

Ответ 3

Я не очень хорошо знаком с Perl, так что простите меня, если это действительно возможно. Но обычно переменные, локальные для фрейма стека, доступны только в этом стеке стека. Вы не можете получить к ним доступ ни с более высокой, ни с более низкой (если вы не выполняете арифметику хакерских указателей, но никогда не гарантируете успеха). К большому числу блоков объявлений с переменными, к сожалению, вам придется жить.

QuantumPete

Ответ 4

perldoc perlguts говорит:

   The "Alias" module implements localization of the basic types within
   the caller scope.  People who are interested in how to localize
   things in the containing scope should take a look there too.

FWIW. Я не смотрел на Alias.pm достаточно близко, чтобы понять, насколько это возможно.

Ответ 5

В TCL вы можете использовать uplevel. Что касается Perl, я не знаю.