【问题标题】:Perl: while ($key = each %hash) doesn't stop at key = 0Perl:while ($key = each %hash) 不会在 key = 0 处停止
【发布时间】:2010-09-18 06:21:31
【问题描述】:

显然,我不需要这个;我只是好奇这里发生了什么。我失踪了吗 简单的东西?我可以在所有版本的 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

【问题讨论】:

    标签: perl hash each while-loop


    【解决方案1】:

    您在标量上下文中调用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。

    另见:When does while() test for defined vs truth 在 PerlMonks 上。我找不到 Perl 文档中提到的地方(提到了 &lt;FILE&gt; 案例,但我没有看到 each 案例)。

    【讨论】:

      【解决方案2】:

      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
      

      【讨论】:

        【解决方案3】:

        谢谢,cjm。 很明显,某种隐式添加了 defined 对于 glob 来说就是这样,但不是在哪里 记录在案。现在至少我知道在有限的情况下 该特殊处理适用。

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

        【讨论】:

          猜你喜欢
          • 2020-11-28
          • 1970-01-01
          • 2015-10-12
          • 2014-06-15
          • 2019-06-15
          • 2019-12-20
          • 2011-03-19
          • 2018-06-27
          • 1970-01-01
          相关资源
          最近更新 更多