我正在浏览Test :: More的代码,因为我想看看use_ok
和require_ok
是如何实现的(以及为什么Ovid不喜欢它们)。我来到了_eval
子程序,其中包含一些我在eval
调用期间保护变量时并不完全理解的特殊逻辑。我从Try::Tiny的文档中了解到处理$@
是多么困难。但是,我不理解$!
和$SIG{__DIE__}
的处理方式(下面的块被逐字复制):
# Work around oddities surrounding resetting of $@ by immediately
# storing it.
my( $sigdie, $eval_result, $eval_error );
{
local( $@, $!, $SIG{__DIE__} ); # isolate eval
$eval_result = eval $code; ## no critic (BuiltinFunctions::ProhibitStringyEval)
$eval_error = $@;
$sigdie = $SIG{__DIE__} || undef;
}
# make sure that $code got a chance to set $SIG{__DIE__}
$SIG{__DIE__} = $sigdie if defined $sigdie;
$SIG{__DIE__}
的处理与RT #34065有关,但我仍然没有得到它。为什么有必要在最后一行再次设置变量,因为它总是应该在块的最后一行设置?如果这些行的重点是将变量设置为eval
调用中的变量,为什么必须首先将其本地化?
此外,如果使用eval
而不使用错误变量错误变量意味着本地化$@
和$!
,我们是否还必须本地化$?
?
答案 0 :(得分:2)
我认为$sigdie
可以明确地允许eval'd代码 set $SIG{__DIE__}
,同时不允许任何外部设置的处理程序在EVAL。
因此本地化会抑制外部值,但需要在块结束之前保存任何设置值,并在块之后将其设置为现在未本地化的版本。
我认为$!
已本地化,但不是$?
,$^E
等,原因是实际原因(也就是说,我猜人们会抱怨$!
更改,但是不是别的什么。)