这个perl包装函数可以扩展为与任何输入函数一起使用吗?

问题描述

| 考虑以下包装函数,如果该函数抛出该函数,则该包装函数将给定次数重试给定次数(不知道为什么格式很奇怪):
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->(@_);
}
无效上下文将作为无效上下文传播,但这可能是可以接受的。如果没有,则很容易调整。     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...