在Try :: Tiny catch块中使用next进行错误处理

时间:2013-05-21 13:48:26

标签: perl exception error-handling try-catch

以下代码(简化示例,我实际上是在对象列表上进行迭代并尝试捕获异常)通过转到for列表中的下一个项目来执行错误处理。它有效,但是在catch子例程中使用循环控制语句时会发出警告:

use strict;
use warnings;
use Try::Tiny;
use 5.010;

NUM: for my $num (1 .. 10) { 
  try { 
    if ($num == 7) { 
      die 'ugly number'; 
    } 
  } catch { 
    chomp;
    say qq/got "$_"/; 
    next NUM; 
  }; 
  say qq/number $num/; 
}

输出:

number 1
number 2
number 3
number 4
number 5
number 6
got "ugly number at testtry.pl line 9."
Exiting subroutine via next at testtry.pl line 14.
Exiting subroutine via next at testtry.pl line 14.
number 8
number 9
number 10

我可以看到两种解决方法 - 使用范围无警告块关闭此用法范围内的警告,或者将错误消息复制到临时变量并在catch之外检查/下一步块。前者可能有我忽略的问题,第二个可能会导致错误处理。哪个更受欢迎,还是有另一种我忽略的方式?

4 个答案:

答案 0 :(得分:6)

在catch块内,放一个no warnings 'exiting'。这将禁用警告。 strictwarnings pragma就是为了帮助你,当他们阻挡你时,可以自由地在词汇上禁用它们。

perldiag页面列出了内置警告和错误类别。您可以通过禁用此类别来查看将被静音的所有消息,并确定它是否值得。

编辑:

您可以利用成功的try返回undef,但如果出错,则会获得catch块的值。这允许我们这样做:

NUM: for my $num (1 .. 10) { 
  try {
    die 'ugly number' if $num == 7;
  } catch { 
    chomp;
    say qq/got "$_"/; 
    return 1;       # return some true value
  } and next NUM;   # go to next iteration here, outside the try/catch
  say qq/number $num/; 
}

但是,我发现no warnings解决方案更优雅,更明显。

答案 1 :(得分:2)

对于这种情况的正确解决方案 - 可能对于您尝试解决的更一般情况 - 是放置只有在try块中没有错误而不是依赖时才会发生的事情在显式循环控制上。看起来像这样:

for my $num (1 .. 10) { 
  try { 
    if ($num == 7) { 
      die 'ugly number'; 
    } 
    say qq/number $num/; 
  } catch { 
    chomp;
    say qq/got "$_"/;
  }; 
}

last是循环控制语句,实际上需要额外注意,因为它必须做的不仅仅是跳过循环体。但请考虑

try {
  for my $num (1 .. 10) { 
    try {
      die 'ugly number' if $num == 7;
      die 'early exit' if $num == 9;
      say qq/number $num/; 
    } catch {
      die $_ if /^early exit/;
      chomp;
      say qq/got "$_"/;
    }; 
  }
};

答案 2 :(得分:0)

另一种解决方法,虽然可能只对这个简化的示例有用,而不是在整个程序中,但是避免将next指令放在死后的代码,例如:

use strict;
use warnings;
use Try::Tiny;
use 5.010;

for my $num (1 .. 10) { 
  try { 
    if ($num == 7) { 
      die 'ugly number'; 
    }   
    say qq/number $num/; 
  } catch { 
    chomp;
    say qq/got "$_"/; 
    #next NUM; 
  }; 
  #say qq/number $num/; 
}

它产生:

number 1
number 2
number 3
number 4
number 5
number 6
got "ugly number at script.pl line 11."
number 8
number 9
number 10

答案 3 :(得分:0)

基本上我正在寻找以下流量控制。我只是不喜欢确定下一个NUM错误处理的范围。

use strict;
use warnings;
use Try::Tiny;
use 5.010;

NUM: for my $num (1 .. 10) { 
  my $e;
  try { 
    if ($num == 7) { 
      die 'ugly number'; 
    } 
  } catch { 
    chomp;
    say qq/got "$_"/; 
    $e = $_; 
  }; 
  if ($e) {
    next NUM;
  }
  say qq/number $num/; 
}