Perl:while($ key =每个%hash)不会在key = 0处停止

时间:2008-10-21 05:43:56

标签: perl hash each while-loop

显然我不需要这个;我只是好奇这里发生了什么。我错过了吗 简单的事情?我可以在所有版本的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(每个)没有解释为什么 当$k被赋值为0时,while循环继续。 代码的行为就像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

3 个答案:

答案 0 :(得分:29)

你在标量上下文中调用each,因为它没有工作,因为列表返回值。

就像

一样
while ($line = <FILE>)

是特殊的,可以添加隐式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的所有版本。

另请参阅:PerlMonks上的When does while() test for defined vs truth。我无法找到Perl文档中提到的位置(提到<FILE>的情况,但我没有看到each情况)。

答案 1 :(得分:6)

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

答案 2 :(得分:0)

谢谢,cjm。 很明显某种隐含的defined加法 对于glob而言,这种情况正在发生,但并非如此 记录。现在至少我知道有限的案例 特殊处理适用。

但是信息应该在perlfunc文档中, 不只是Perl源代码!