从子例程结束循环的迭代

时间:2014-09-12 12:16:48

标签: perl loops subroutine

我有一个带有while循环的程序,它有几个点,某些条件需要采取某些操作,然后跳过剩余的迭代。

因为这总是相同的代码,我想把它放在子程序中,但当我尝试使用'next;'时作为子中的最后一个语句,我得到一个警告(通过下一个在......退出子程序),虽然它似乎按预期工作。

即。没有子:

while (#condition) {

    ## do stuff

    if (#condition to skip iteration) {
        ## action
        next;
    }

    ## do more stuff, with the above block repeated several times
}

with sub:

while (#condition) {

    ## do stuff

    &skip if (#condition to skip iteration);

    ## do more stuff, with more calls to &skip
}

sub skip() {
    ## action
    next;
}

块/ sub中的其余代码非常短,除了下一个之外的其他所有代码; sub中的语句几乎违背了使用子程序的目的。

我的问题是:

  • 正在使用'next;'以这种方式在子程序中好,还是危险/差的做法?
  • 是否有更好的方法可以跳过子程序中的其余迭代?
  • 如果没问题并且没有更好的方法,有没有办法抑制警告?

5 个答案:

答案 0 :(得分:8)

很容易抑制警告。只需将以下行放在next

上方
no warnings "exiting";

警告是有原因的 - 在帮助程序子中使用next可能会让下一个必须阅读代码的人感到困惑(可能是6个月后的人!)因为next不会在循环块内以词汇方式出现。如果您只是阅读循环块,您可能不会注意到文件中的next;如果你只是阅读子程序的定义,你可能不确定那是next的用途。您需要一起阅读代码的两个部分才能理解它。这比在循环中直接使用next更令人困惑。

此外,它限制了您刚刚定义的skip()子的重新可用性。想在另一个循环中重用那个skip() sub?你最好希望跳过逻辑在新循环中仍然有意义。

如果您已经考虑了所有这些但仍想继续进行,那么只需禁用上面显示的警告即可。 警告不是错误,它们只是警告。这就是为什么警告被称为“警告”。它们旨在引起您对潜在问题的关注;不要阻止你做你认为有用的事情。

答案 1 :(得分:6)

来自 Learning perl第6版第179页(脚注)

  

这可能不是一个好主意,但你可以使用这些循环控制   从子程序内部的操作符来控制外部的循环   子程序。也就是说,如果在循环块中调用子例程,   当没有循环块运行时,子程序最后执行   在子程序内部,控制流将跳转到刚刚之后   主代码中的循环块。 这种使用循环控制的能力   在子程序中可能会在未来的Perl版本中消失,而不是   一个人可能会错过它。

解决方案可能是其他人已经说过的,或者你可以在sub中进行额外的测试,比如

use strict;
use warnings;

while(<>) {
    chomp;
    maybeskip($_) && next if m/2/; #maybe skip if match 2
    print "$_\n";
}

sub maybeskip {
    $_[0] !~ m/0/; #skip only if not match 0
    # the sub retuns the result of the last executed expression
    # if this is not wanted you should use explicit return $value;
}

用于

seq 25 | perl script

打印:

1
3
4
5
6
7
8
9
10
11
13
14
15
16
17
18
19
20

e.g。已跳过所有匹配的2,但未跳过20

答案 2 :(得分:4)

你的警告本能可能是对的。如你所说,next只是不是那种嵌入子程序的语句。即使你不喜欢它,这几乎肯定更好:

while (#condition) {

    ## do stuff

    &skip, next if (#condition to skip iteration);

    ## do more stuff, with more calls to &skip
}

sub skip() {
    ## action
}

(我碰巧对非标准编程技术有一种相当宽松的态度​​,特别是如果它们没有被过度使用。如果你强烈想要在这个实例中嵌入next,那么我不会和你争论,因为这是你的程序。然而,尽管如此,既然你已经征求过建议,我同意你的直觉,即嵌入next可能不是一个好主意。)

答案 3 :(得分:3)

如果这是一个好习惯,警告不会发出警告。使用您的函数,使其早期返回而不是next。您可以检查功能结果并决定是跳到下一次迭代,还是无条件跳到下一次,

use warnings;

sub foo {
  print ($_, "\n");
}

for (1..10) {
  foo(), next if $_ %2;;
}

答案 4 :(得分:3)

您可以将部分/全部跳过条件放入子例程中,将truthy返回到next并使用false {0}继续使用and运算符。

while (#condition) {

    ## do stuff

    &skip and next if (#condition to skip iteration);

    ## or like this
    next if (#condition to skip iteration) and &skip;

    ## or like this
    (#condition to skip iteration) and &skip and next;

    ## do more stuff, with more calls to &skip
}

sub skip() {
    ## action
    return $common_skip_condition;
}