raf*_*afl 2 perl evaluation operators autovivification
今天,当我在 Perl 中发现以下行为时,我感到很惊讶:
sub f { die if %{ $_[0] }; 42 }
my %h;
$h{x} ||= f(\%h); # we die. $_[0] references a hash with an 'x' key during f's run-time
Run Code Online (Sandbox Code Playgroud)
相反,在相同的设置下,以下语句的行为有所不同。
$h{x} = $h{x} || f(\%h); # $h{x} is now 42
Run Code Online (Sandbox Code Playgroud)
分配或与分配和逻辑或的组合之间的潜在差异是否记录在某处?
如果这是由于自动激活造成的,那么模块中是否存在错误或缺少功能autovivification,似乎无法检测到此特定构造中的自动激活?
关键信息:
||并且||=是短路的,因此它们必须先评估左侧,然后再评估右侧。(这允许f() || die()。)
=先评估其右侧操作数,然后再评估左侧操作数。(这允许$x = f($x)。)
的左侧||=仅计算一次。
除非必要(即在左值上下文中),否则哈希元素不会在访问时生动化(创建)。
我们来看一下$h{x} = $h{x} || f(\%h);。
综上所述,我们得出以下结论:
$h{x}需要使元素生动起来。$h{x}返回后评估最左边的值f。我们来看一下$h{x} ||= f(\%h);。
综上所述,我们得出以下结论:
$h{x}必须在调用之前进行评估f。$h{x}必须产生可修改的值,因此它必须生动$h{x}。左值上下文
||=)。\。$_ = uc($_) for @a;)。sub ucip { $_[0] = uc($_[0]) }),但请参阅下面的“一个例外”。一个例外
如果你传递$h{x}给一个子进程,Perl 实际上会传递一个神奇的标量来代理$h{x}。这样做是为了尽可能防止复活。它并不便宜,但它避免了很多令人讨厌的意外。
Perl 有可能$h{x} ||= f(\%h);使用相同的机制来延迟激活,但不值得为此付出代价。