【问题标题】:Alternative to "last" in do loops在 do 循环中替代“last”
【发布时间】:2011-05-21 03:37:37
【问题描述】:

根据last (http://perldoc.perl.org/functions/last.html) 的perl 手册,last 不能用于跳出do {} 循环,但它没有提及替代方案。我正在维护的脚本具有以下结构:

do {
    ...
    if (...) 
    {
        ...
        last;
    }
} while (...);

我很确定他想走到循环的末尾,但它实际上退出了当前子例程,所以我需要更改 last 或重构整个循环,如果有更好的方法有人可以推荐。

【问题讨论】:

  • 替代方法是不使用do {}

标签: perl control-flow do-loops


【解决方案1】:

将do“循环”包装在一个裸块中(一个循环):

{
    do {
        ...
        if (...) 
        {
            ...
            last;
        }
    } while (...);
}

这适用于最后和重做,但不适用于下一个;将裸块放在 do 块内:

do {{
    ...
    if (...) 
    {
        ...
        next;
    }
    ...
}} while (...);

【讨论】:

  • perlsyn 中提到了这一点,尽管我认为如果您在裸块和 last 语句中使用标签会更清楚。
  • 我一直都知道,Perl 是一门病态的语言! do-while-loops 实际上没有循环,但裸块是循环 ::facepalm:: 无论如何,我还是喜欢 Perl,因为它非常 hacky,你可以快速而肮脏地解决复杂的问题,“非常肮脏” ;-) +1为您的解决方案。
【解决方案2】:

do BLOCK while (EXPR) 很有趣,因为 do 并不是真正的循环结构。所以,last、next 和 redo 不应该在那里使用。当发现这种情况时,去掉最后一个并调整 EXPR 以评估 false。 另外,打开严格,这应该至少给你一个警告。

【讨论】:

    【解决方案3】:

    从不喜欢 Perl 中的 do/while 循环。 do 并不是一个真正的循环,这就是为什么last 不会摆脱它。在我们旧的Pascal 发呆中,您无法在中间退出循环,因为那是错误的,根据圣人 Niklaus “一个入口/一个出口” Wirth 的说法。因此,我们必须创建一个退出标志。在 Perl 中它看起来像这样:

    my $endFlag = 0;
    do {
        ...
        if (...) 
        {
            ...
            $endFlag = 1;
        }
    } while ((...) and (not $endFlag));
    

    现在,您可以看到帕斯卡从未流行过。

    【讨论】:

    • Pascal 在教学语言方面并没有那么糟糕 :) 但我很高兴我再也不用看(或天堂禁止写)另一行 Pascal 代码了。
    • 如果只有这个和其他任何事情可以阻止 VBscript 流行起来。
    【解决方案4】:

    为什么不直接使用 while 循环?

    while (...) {
      ...
      if (...) {
        last;
      }
    }
    

    您可能需要稍微更改您的逻辑以适应您的测试在循环的开头而不是结尾的事实,但这应该是微不足道的。

    顺便说一句,如果您使用 Delphi,您实际上可以跳出 Pascal 循环,并且 Delphi DID 流行了一段时间,直到 Microsoft 明智并推出了 .net 语言。

    【讨论】:

    • +1 用于 Delphi 提及 :) 。我真的很喜欢德尔福。我还使用它的链接器和 DOS C 编译器来编写 Win32 C 程序:)。
    【解决方案5】:

    @“http://perldoc.perl.org/functions/last.html”: last 不能用于退出返回值的块,例如 eval {} 、 sub {} 或 do {} ,也不应用于退出 grep() 或 map() 操作。

    所以,在 'while()' 中使用一个布尔值并将其设置在你拥有 'last' 的位置...

    【讨论】:

      【解决方案6】:

      聚会迟到了——我最近一直在和for(;;) 搞混。在我的初步测试中,对于条件表达式AB,你想要做什么:

      do {
          last if A;
      } while(B);
      

      可以这样实现:

      for(;; B || last) {
          last if A;
      }
      

      有点难看,但可能不比其他解决方法更难:)。一个例子:

      my $i=1; 
      for(;; $i<=3 || last) { 
          print "$i ";
          ++$i;
      }
      

      输出1 2 3。如果需要,您可以组合增量:

      my $i=1;
      for(;; ++$i, $i<=3 || last) { 
          print "$i ";
      }
      

      (使用||,因为它的优先级高于,

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-26
        • 2021-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多