是否有一种更清洁的方式来有条件地“持续”出这个Perl循环?

时间:2011-09-07 13:27:11

标签: perl syntactic-sugar

我并不真正了解Perl,在友好的搜索引擎的帮助下,我一直在增强Perl脚本。

我发现如果条件成立,我需要在设置标志时突破循环:

foreach my $element (@array) {
    if($costlyCondition) {
        $flag = 1;
        last;
    }
}

我知道使用'last'的更好方式是这样的:

foreach my $element (@array) {
    last if ($costlyCondition);
}

当然,这意味着虽然我可以享受语法糖,但我无法在循环中设置我的旗帜,这意味着我需要再次在外面评估$costlyCondition

有更简洁的方法吗?

4 个答案:

答案 0 :(得分:21)

您可以使用do {...}块:

do {$flag = 1; last} if $costlyCondition

您可以使用,运算符加入语句:

$flag = 1, last if $costlyCondition;

您可以对逻辑&&运算符执行相同操作:

(($flag = 1) && last) if $costlyCondition;

甚至是较低优先级and

(($flag = 1) and last) if $costlyCondition;

在一天结束时,没有任何理由去做这些事情。它们都与原始代码完全相同。如果您的原始代码有效并且清晰易读,请保持原样。

答案 1 :(得分:7)

我同意Nathan的看法,虽然整洁的代码很整洁,但有时可读的版本更好。尽管如此,这是一个可怕的版本:

last if $flag = $costly_condition;

请注意使用赋值=而不是相等==。赋值将返回$costly_condition中的任何值。

这当然不会$flag = 1,而是$costly_condition。但是,既然这需要成立,那么$flag也是如此。为了解决这个问题,你可以 - 正如Zaid在评论中提到的那样 - 使用:

last if $flag = !! $costly_condition;

如上所述,非常糟糕的解决方案,但它们确实有效。

答案 2 :(得分:5)

一种想法是在子程序中执行循环,该子程序根据退出点返回不同的值。

my $flag = check_elements(\@array);

# later...

sub check_elements {
  my $arrayref = shift;
  for my $ele (@$arrayref) {
    return 1 if $costly_condition;
  }
  return 0;
}

答案 3 :(得分:0)

这是可能的,但强烈建议不要这样做:这样的技巧会降低代码的可读性。

foreach my $element (@array) {
    $flag = 1 and last if $costlyCondition;
}