Как я могу локализовать переменные Perl в другом фрейме стека? - PullRequest
24 голосов
/ 14 октября 2008

У меня есть некоторый автоматически сгенерированный код, который эффективно записывает следующее в нескольких местах в некотором коде:

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 ]

30 голосов
/ 14 октября 2008

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

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
});
6 голосов
/ 14 октября 2008

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

Существуют некоторые экспериментальные модули, такие как Sub :: Uplevel и Devel :: RunBlock , которые позволяют вам попытаться «обмануть» caller() для подпрограмм или сделать «длинный» переходить от значений к более высоким кадрам стека (соответственно), но ни один из них не влияет на то, как local обрабатывает переменные (я пытался.:)

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

3 голосов
/ 15 октября 2008

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, чтобы понять, насколько это легко.

3 голосов
/ 14 октября 2008

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

QuantumPete

1 голос
/ 14 октября 2008

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

0 голосов
/ 18 октября 2008

Perl имеет Sub :: Uplevel

...