问题描述
|
考虑以下包装函数,如果该函数抛出该函数,则该包装函数将给定次数重试给定次数(不知道为什么格式很奇怪):
sub tryit{
my $fun = shift;
my $times = shift;
my @args = @_;
my $ret;
do{
$times--;
eval{
$ret = $fun->(@args);
};
if($@){
print \"Error attemping cmd: $@\\n\";
}
else{
return $ret;
}
}while($times > 0);
return;
}
无论如何返回哪种类型的值,该如何扩展才能正确设定参数函数的返回值?例如,此函数将无法正确传递数组。您不能只返回$ fun->(),因为返回只会使您退出评估块。
解决方法
您可以使用wantarray进行此操作。 (它对我来说也很格式化;对不起)
sub tryit{
my $fun = shift;
my $times = shift;
my @args = @_;
my $array_wanted = wantarray;
my $ret;
my @ret;
do{
$times--;
eval{
if ($array_wanted) {
@ret = $fun->(@args);
}
else {
$ret = $fun->(@args);
}
};
if($@){
print \"Error attemping cmd: $@\\n\";
}
else{
if ($array_wanted) {
return @ret;
}
else {
return $ret;
}
}
}while($times > 0);
return;
}
我敢肯定,Perl怪兽黑客会找到一种方法来加强这一点,但这是基本思想。
, 基本答案与Nemo相同,但有一些改进:
更安全的异常处理。
未捕获最后一次尝试的例外。
错误发送到STDERR。
多余的换行符已删除。
清洁循环。
更好的变量名。
wantarray
将为您提供所需的信息。
sub tryit {
my $func = shift;
my $attempts = shift;
my $list_wanted = wantarray;
my @rv;
for (2..$attempts) {
if (eval{
if ($list_wanted) {
@rv = $func->(@_);
} else {
$rv[0] = $func->(@_);
}
1 # No exception
}) {
return $list_wanted ? @rv : $rv[0];
}
warn($@,\"Retrying...\\n\");
}
return $func->(@_);
}
无效上下文将作为无效上下文传播,但这可能是可以接受的。如果没有,则很容易调整。