显然,我不需要这个; 我只是好奇这里发生了什么.我错过了一些简单的事吗?我可以在所有版本的Perl中依赖此行为吗?)
Perl v5.8.8:
%h = ( 0=>'zero', 1=>'one', 2=>'two' ); while ($k = each %h) { $v = delete $h{$k}; print "deleted $v; remaining: @h{0..2}\n"; }
输出
deleted one; remaining: zero two deleted zero; remaining: two deleted two; remaining:
man perlfunc
(每个)没有解释为什么while循环在$k
分配0 时继续.代码的行为就像while
循环上的条件一样($k = each %h, defined $k)
.
如果循环条件实际上已更改为,
($k = each %h, $k)
那么它确实会$k = 0
按预期停止.
它还会停止$k = 0
以下重新实现each
:
%h = ( 0=>'zero', 1=>'one', 2=>'two' ); sub each2 { return each %{$_[0]}; } while ($k = each2 \%h) { $v = delete $h{$k}; print "deleted $v; remaining: @h{0..2}\n"; }
输出只是:
deleted one; remaining: zero two
cjm.. 29
你each
在标量上下文中调用,因为它没有工作,因为列表返回值.
就像
while ($line =)
是特殊的,添加一个隐含的defined
,所以是
while ($key = each %hash)
在5.8.8中,这发生在op.c,第3760-3766行:
case OP_SASSIGN: if (k1->op_type == OP_READDIR || k1->op_type == OP_GLOB || (k1->op_type == OP_NULL && k1->op_targ == OP_GLOB) || k1->op_type == OP_EACH) expr = newUNOP(OP_DEFINED, 0, expr); break;
我不确定这是否适用于所有版本的Perl 5.
另请参阅:while()测试 PerlMonks上的已定义vs真值.我无法找到Perl文档中提到的位置(提到的
情况,但我没有看到这种each
情况).
你each
在标量上下文中调用,因为它没有工作,因为列表返回值.
就像
while ($line =)
是特殊的,添加一个隐含的defined
,所以是
while ($key = each %hash)
在5.8.8中,这发生在op.c,第3760-3766行:
case OP_SASSIGN: if (k1->op_type == OP_READDIR || k1->op_type == OP_GLOB || (k1->op_type == OP_NULL && k1->op_targ == OP_GLOB) || k1->op_type == OP_EACH) expr = newUNOP(OP_DEFINED, 0, expr); break;
我不确定这是否适用于所有版本的Perl 5.
另请参阅:while()测试 PerlMonks上的已定义vs真值.我无法找到Perl文档中提到的位置(提到的
情况,但我没有看到这种each
情况).
cjm是对的.我只是想补充一点,当遇到像这样的奇怪事情时,通常可以通过B :: Deparse运行代码,看看Perl如何理解你的代码.我喜欢使用-p开关来显示优先级错误.
$ perl -MO=Deparse,p your_example.plx (%h) = (0, 'zero', 1, 'one', 2, 'two'); while (defined($k = each %h)) { $v = delete $h{$k}; print "deleted $v; remaining: @h{0..2}\n"; } your_example.plx syntax OK