28

这个刚刚出现:我如何打破一个if声明?我有一个很长的 if 语句,但有一种情况我可以尽早摆脱它。

在一个循环中,我可以这样做:

while (something ) {
    last if $some_condition;
    blah, blah, blah
    ...
}

但是,我可以对 if 语句做同样的事情吗?

if ( some_condition ) {
    blah, blah, blah
    last if $some_other_condition; # No need to continue...
    blah, blah, blah
    ...
}

我知道我可以将if语句放在一个块中,然后我可以跳出块:

{
    if ( some_condition ) {
        ...
        last if $some_other_condition; # No need to continue...
        blah, blah, blah
        ...
    }
}

或者,我可以创建一个子例程(以编程方式可能更好):

if ( some_condition ) {
    run_subroutine();
}

sub run_subroutine {
    blah, blah, blah
    return if $some_other_condition;
    blah, blah, blah
    ...
}

但是有没有办法退出一个if条件?


解析度

出现这个问题是因为我正在帮助某人编写代码。在相当长的声明中,还嵌入if了其他几条声明。if代码看起来像这样:

 if ( $condition1 ) {
    blah, blah, blah;
    if ( not $condition2 ) {
       blah, blah, blah;
       if ( not $condition3 ) {
          blah, blah, blah;
       }
    }
}

我认为通过这样做可以使整个内容更具可读性:

if ( $condition1 ) {
    last if $condition2;
    blah, blah, blah;
    last if $condition3;
    blah, blah, blah;
}

这表明该if语句的正常流程是标准的,但在某些条件下,该if语句被提前退出——很像在or循环中使用lastor来退出循环。nextwhilefor

我喜欢mpapec使用标签的解决方案——即使我不使用标签本身。标签是我的描述if

IF-UNDER-CONDITION1:
{
    if ( $condition1 ) {
        last if $condition2;
        blah, blah, blah;
        last if $condition3;
        blah, blah, blah;
    }
}

虽然它不是一种标准的编码技术,但代码的流动是显而易见的,一个典型的低级 Perl 开发人员(我离开后必须维护这段代码的人)可以弄清楚代码在做什么并维护它. 他们甚至可能在此过程中学到一些东西。

4

7 回答 7

30

您可以使用受,和约束的基本块,因此可能会中断。lastnextredo

if ($condition) {EXIT_IF:{

   last EXIT_IF; # break from code block

   print "never get's executed\n";
}}

EXIT_IF: {
  if ($condition) {

     last EXIT_IF; # break from code block

     print "never get's executed\n";
  }
}
于 2013-06-11T21:01:27.597 回答
3
  • 将它放在一个空for()循环中,并last;if. 有点难看但有效。确保添加评论来解释这个技巧。

    for (;;) {
        if (condition) { 
            #code
            last if another_condition;
        }
        last;
    }
    
  • 在该 goto 的循环之后使用goto并标记语句。永远被诅咒。

  • if(例如if () {{ code }})内的额外块。对于新手来说可能很难阅读,但如果附有评论就可以了。

  • 您自己的解决方案:阻止if. 不是很明显的可读性。

  • 您自己的解决方案:带返回的子程序。

    坦率地说,除非调用 sub 的成本在性能方面很重要,否则就可读性而言,这是最干净的解决方案

于 2013-06-11T20:58:55.087 回答
2

您可以将if块的其余部分放在另一个if语句中,如下所示:

if (some_condition) {
    blah, blah, blah
    if (!$some_other_condition) {
        blah, blah, blah
        ...
    }
}
于 2013-06-11T20:58:56.580 回答
0

我倾向于使用基于“我继续吗?”的顺序 if 语句。改为变量。您的

if ( $condition1 ) {
  blah, blah, blah;
  if ( not $condition2 ) {
     blah, blah, blah;
     if ( not $condition3 ) {
        blah, blah, blah;
     }
  }
}

可以重新排列为

my $ok = $condition1;
if ($ok) {
  blah, blah, blah;
  $ok = not $condition2;
}
if ($ok) {
  blah, blah, blah;
  $ok = not $condition3;
}
if ($ok) {
  blah, blah, blah;
}
于 2014-11-06T09:16:31.120 回答
0

另一种选择是使用匿名子例程。
注意:我不推荐这种方法,因为它增加了作用域的复杂性(见下面的注释);这只是为了可能答案的完整性。

if( $true_condition ){
   (sub{
       return if $true_condition;
       ...
   })->();
}

注意:在例程中声明的任何变量都必须使用our,而不是my如果您希望在其余代码中使用它们。

于 2013-06-11T21:02:43.447 回答
0

保留你的while循环,以便你可以使用last ,但也要确保循环最多执行一次

my $loop_once = 1;
while ( $loop_once-- and some_condition ) {
    blah, blah, blah
    last if $some_other_condition; # No need to continue...
    blah, blah, blah
    ...
}
于 2014-12-01T17:34:20.337 回答
0

我受到DVK 的回答的启发,我想出了这个至少在 Perl 5.26.1 上有效的变体:

for( ; some_condition ; last ) {
    blah, blah, blah
    last if $some_other_condition; # No need to continue...
    blah, blah, blah    
}

perlsyn,这相当于:

while (some_condition) {
    blah, blah, blah
    last if $some_other_condition; # No need to continue...
    blah, blah, blah    
} continue {
    last;
}

在一个continue块中,last与在主循环中执行的效果相同。因此,循环将执行 0 次或 1 次,具体取决于some_condition.

测试

perl -E 'my ($cond, $other)=(X, Y); 
         for(;$cond;last) { say "hello"; last if $other; say "goodbye" }'

X对于各种和Y值,具有以下结果:

X Y   Prints
-----------------------
0 0   (nothing)
0 1   (nothing)
1 0   hello, goodbye
1 1   hello
于 2018-04-10T15:14:02.410 回答