即使我从Try :: Tiny的finally块中返回一个值,为什么我会得到'使用未初始化值'的警告?
问题描述:
目前还不清楚我为什么下面的一段代码给我的错误:即使我从Try :: Tiny的finally块中返回一个值,为什么我会得到'使用未初始化值'的警告?
Use of uninitialized value in addition (+) at combined_op_test.pl line 12.
我期待的$success_count
值由在每次迭代子程序的返回值递增。
下面是代码:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
use Try::Tiny;
my $success_count = 0;
for (1..10) {
$success_count += error_causing_sub();
}
sub error_causing_sub {
try {
die ("Error.");
} catch {
} finally {
if (@_) {
say "Error occured.";
return 0;
}
else {
say "Error did not occur.";
return 1;
}
};
}
任何帮助表示赞赏。
答
如在文档的CAVEATS部分解释的,return
不从子返回,从finally
返回:
return
returns from thetry
block, not from the parentsub
(note that this is also howeval
works, but not howTryCatch
works):sub parent_sub { try { die; } catch { return; }; say "this text WILL be displayed, even though an exception is thrown"; }
由于@simbabque notes的finally
返回值被忽略。如果try
出现故障,catch
返回值是相关的,它是空的:
The return value of the
catch
block is not ignored, so if testing the result of the expression for truth on success, be sure to return a false value from thecatch
block: ...
下面的代码看起来更合乎逻辑的对我说:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
use Try::Tiny;
my $success_count = 0;
for (1..10) {
$success_count += error_causing_sub();
}
say $success_count;
sub error_causing_sub {
my $ret;
try {
die ("Error.") if rand(1) < 0.5;
say "Error did not occur.";
$ret = 1;
} catch {
say "Error occured.";
$ret = 0;
};
return $ret;
}
此外,据我所知,the issues with eval
that made Try::Tiny
relevant were fixed in 5.14。所以,使用它可能会更好:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.014;
my $success_count = 0;
$success_count += error_causing_sub() for 1 .. 10;
say $success_count;
sub error_causing_sub {
my $ret;
eval {
die ("Error.") if rand(1) < 0.5;
say "Error did not occur.";
$ret = 1;
} or do {
say "Error occured.";
$ret = 0;
};
return $ret;
}
这并不完全。 'finally'的RV被忽略。如果失败,catch的RV是相关的,并且是空的。没时间写我自己的答案。你可以通过改变'catch {1}'来看到 – simbabque
5.14固定的if($ @)'。最后一个片段不使用'if($ @)',所以它在5.14之前就可以工作。 – ikegami