1

我有以下声明:

my $iii=0;
while (my @row = sub_undef()) { print $iii++."\n"; }

sub sub_undef {

  if ($error) {
    return "something that will end the while loop";
  } else {
    return 1;
  }
}

在 sub_undef() 中,当我需要返回将结束 while 循环的内容时,我可能会遇到一个案例(错误)。任何想法如何做到这一点?

——德米特里

4

4 回答 4

5

在布尔上下文中,空数组为 false 1 :

return () if $error;

return方便的是,如果您不指定参数,这就是默认设置,因此您甚至可以只写:

return if $error;

1)这里的一个微妙之处是,在标量上下文中,空数组的计算结果为 0(即它的长度),而空列表的计算结果为undef

@a = (); $b = @a;  # now $b is 0
$b = ();           # now $b is undef

但是,由于 0 和undef在布尔上下文中都是假的,所以这里的区别并不重要。有关详细信息,请参阅perldata


编辑:如果您需要将错误条件与仅仅用完数据区分开来,最好使用for errors引发异常die并返回一个空列表作为数据结束。然后你的循环看起来像这样:

eval {
    while (my @row = sub_undef()) { 
        # do something with @row
    }
};
if ($@) {
    # oops, we got an error, handle it
}

或者,使用Try::Tiny

try {
    while (my @row = sub_undef()) { 
        # do something with @row
    }
} catch {
    # oops, we got an error, handle it
};
于 2013-04-12T18:48:03.563 回答
4

有几种方法:

解决方案1:如果您不需要返回一行,只需返回一个假标量:

sub sub_undef {
    # xxx
    return $error; # Already a true/false scalar
}
while (sub_undef()) { do_stuff(); }

解决方案2:返回一个arrayref而不是一个数组,如果出错则返回false(undef)

sub sub_undef {
    # xxx
    return $error ? undef : $rowArrayRef;
}
while (my $row = sub_undef()) { do_stuff(@$row); }

解决方案 3:返回一个元组 ($status, $rowArrayRef)

sub sub_undef {
    # xxx
    return ($error, $rowArrayRef);
}
while (my ($error, $row) = sub_undef()) { last if $error; do_stuff(@$row); }

解决方案 4:仅当行不能为空时才有效,除非根据您的业务案例发生错误!

sub sub_undef {
    # xxx
    return $error ? () : @row;
}
while (my @row = sub_undef()) { do_stuff(@row); }

解决方案 5:使用异常处理错误 ( Try::Tiny)

# No example worth bothering that won't be covered by Synopsis of the module
于 2013-04-12T18:43:00.640 回答
2

return 1似乎表明你真的想返回一个标量。如果您按如下方式编写循环

while (my ($value) = iter()) {
   ...
}

那么你可以发出三种状态的信号:

  • return $value;成功返回。由于 中的括号my ($value),您甚至可以安全地返回一些 false 或 undefined 而不会导致循环退出。

  • return;当您的迭代器已用尽时。这将导致执行在循环后继续。

  • die "message"发出错误信号。这将导致程序结束,除非eval BLOCK用于捕获异常。

于 2013-04-12T20:16:06.967 回答
1

空列表的分配将评估为假。

  if ($error) {
    return ();
  } else {
    return 1;
  }
于 2013-04-12T18:50:32.567 回答