以下代码(简化示例,我实际上是在对象列表上进行迭代并尝试捕获异常)通过转到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之外检查/下一步块。前者可能有我忽略的问题,第二个可能会导致错误处理。哪个更受欢迎,还是有另一种我忽略的方式?
答案 0 :(得分:6)
在catch块内,放一个no warnings 'exiting'
。这将禁用警告。 strict
和warnings
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/;
}