如何在不同的堆栈框架中本地化Perl变量?

时间:2008-10-14 09:57:58

标签: perl scope local

我有一些自动生成的代码,可以在一些代码中的许多不同位置有效地写出以下内容:

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 个答案:

答案 0 :(得分:30)

也许您可以安排使用这些本地生成的代码作为闭包生成?那么你可以

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

答案 1 :(得分:6)

不确定为什么QuantumPete被投票,他似乎是正确的。你不能告诉local初始化调用块中的变量。它的功能很特殊,它的初始化/拆卸只能在运行它的块上运行。

有一些实验性模块,例如Sub::UplevelDevel::RunBlock,允许您尝试“愚弄”caller()子程序或对值更高的堆栈进行“长跳转”帧(分别),但这些都不会影响local如何处理变量(我试过。:)

所以现在看来​​,您确实需要使用您需要的范围内的本地声明。

答案 2 :(得分:3)

我对Perl并不十分熟悉,请原谅我,如果它真的可行的话。但通常,堆栈帧本地的变量仅在该堆栈帧中可用。您无法从更高或更低的位置访问它们(除非您执行一些hacky指针算法,但从未保证成功)。 不幸的是,大块的变量声明是你不得不忍受的。

QuantumPete

答案 3 :(得分:3)

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,看看它有多容易。

答案 4 :(得分:1)

在TCL中,您可以使用uplevel。至于Perl,我不知道。

答案 5 :(得分:0)

Perl有Sub::Uplevel