Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Perl中将变量本地化到更高的作用域中?_Perl_Local_Goto_Uplevel - Fatal编程技术网

如何在Perl中将变量本地化到更高的作用域中?

如何在Perl中将变量本地化到更高的作用域中?,perl,local,goto,uplevel,Perl,Local,Goto,Uplevel,在开发使用自动加载或其他子例程分派技术的Perl模块时,我曾多次遇到以下模式: sub AUTOLOAD { my $self = $_[0]; my $code = $self->figure_out_code_ref( $AUTOLOAD ); goto &$code; } 这工作正常,caller可以看到正确的范围 现在我想做的是在执行和$code的过程中,将$\ucode>本地设置为等于$self。可能是这样的: sub AUTOLOAD {

在开发使用
自动加载
或其他子例程分派技术的Perl模块时,我曾多次遇到以下模式:

sub AUTOLOAD {
    my $self = $_[0];

    my $code = $self->figure_out_code_ref( $AUTOLOAD );

    goto &$code;
}
这工作正常,
caller
可以看到正确的范围

现在我想做的是在执行
和$code
的过程中,将
$\ucode>本地设置为等于
$self
。可能是这样的:

sub AUTOLOAD {
    my $self = $_[0];

    my $code = $self->figure_out_code_ref( $AUTOLOAD );

    local *_ = \$self;

    # and now the question is how to call &$code

    # goto &$code;  # wont work since local scope changes will 
                    # be unrolled before the goto

    # &$code;  # will preserve the local, but caller will report an
               # additional stack frame  
}
由于性能和依赖性问题,涉及包装调用方的解决方案是不可接受的。所以这似乎排除了第二种选择

回到第一个问题,防止
$\ucode>的新值在
goto
期间超出范围的唯一方法是不本地化更改(不是可行的选项),或者实现某种
uplevel\u local
goto\u with\u local

我已经尝试过各种各样的排列,包括
PadWalker
Sub::Uplevel
Scope::Upper
B::Hooks::EndOfScope
和其他,但还没能找到一个在正确的时间清理
$\ucode>并且不包装
调用方的健壮解决方案

有没有人找到一种在这种情况下有效的模式


(所谓的问题:是相关的,但保留调用方并不是一个要求,最终的答案是使用不同的方法,因此解决方案在这种情况下没有帮助)

Sub::Uplevel似乎起作用——至少对于不涉及自动加载的简单情况:

use strict;
use warnings;
use Sub::Uplevel;

$_ = 1;
bar();

sub foo {
    printf  "%s %s %d - %s\n", caller, $_
}

sub bar {
    my $code = \&foo;
    my $x    = 2;
    local *_ = \$x;
    uplevel 1, $code;
}
输出为:

main c:\temp\foo.pl 6 - 2

当然,这并没有真正地在父范围内本地化变量,但我认为即使可以,您也不会真的希望这样做。您只想在通话期间本地化
$。

转到
的perlfunc文档指出(重点已添加)

goto-&NAME
形式与其他形式的“goto”有很大不同。事实上,它根本不是一个正常意义上的后继,也没有与其他后继相关的污名。相反,它退出当前子例程(丢失
本地设置的任何更改)


什么样的性能问题允许通过自动加载而不是通过包装进行间接寻址?

老实说,我在这里有点迷茫。但是你能帮我们做一下吗?因此,您可以在本地访问$uu,但也可以访问$套餐:$\说真的,尽管这超出了我的大脑scope@xenoterracide=>我不确定您的软件包范围想法将走向何方,但是
$\ucode>(以及大多数其他标点符号变量)在所有软件包中都很常见,并且不能用
我们的
来确定软件包范围。词法
$\u
my$\u;
)是一个完全不同的野兽,但这超出了这个问题的范围,请原谅,我不确定我要带它去哪里。但是perl并没有对我们的$大喊大叫所以我假设$也会受到影响;也许假设错了。如果我有一个真实的答案,我会这样回答。这是为了什么?首先,您为什么要本地化
$\uuu
,这会带来什么好处?@Ether=>在我的例子中,纯粹是出于风格原因(消除锅炉板代码),这就是为什么我要重视CORE::GLOBAL修改对性能的影响,因为风格上的调整不应该导致深远的性能问题。但我可以想象
uplevel\u local
goto\u with\u local
构造的其他用途。
Sub::uplevel
将完成欺骗
调用者的任务,但我对它的方式并不着迷(包装和本地化
CORE::GLOBAL::caller
)。有关更多详细信息,请参见
Sub::Uplevel
的BUGS/Cautions部分。啊,我(错误地)将您的问题理解为“Sub::Uplevel不起作用”,而不是您因为它的工作方式而取消了它的资格。我对性能的关注更多的是针对我没有编写的代码(模块用户)。我不能说他们是否会使用
调用者
或广泛使用
调用者
的代码,从C内置到userland sub的性能影响可能很大。由于最终的目标只是为您设置
$\uucode>的语法精确性,因此很难证明对
核心::全局
命名空间的更改是合理的,这可能会导致性能下降。我想我的最终问题是,我不同意在
转到
之前展开局部变量的设计决策,因为它似乎不必要地降低了
goto-&NAME
构造的能力。我更希望
goto-&NAME
从呼叫站点采用本地pad,然后在
&NAME
执行结束时回滚本地pad。这可能也比每次弹出和推送作用域堆栈要快。