首页 文章

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

提问于
浏览
9

下面的代码(一个简化的例子,我实际上迭代对象列表并试图捕获异常)通过转到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

    另一种解决方法,虽然可能只对这个简化的示例有用,而不是在整个程序中,但是避免将 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
    
  • 7

    在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 解决方案更优雅,更明显 .

  • 0

    对于这种情况的正确解决方案 - 可能对于您试图解决的更一般的情况 - 是放置只有在 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

    基本上我正在寻找以下流量控制 . 我只是不喜欢确定下一个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/; 
    }
    

相关问题