Consider the following wrapper function that retrys a given function some given number of times if the function throws (not sure why the formatting is wonky):
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;
}
How can this be extended so that the return value of the parameter function is properly propigated up no matter what kind of value is returned? For instance, this function won't pass an array up properly. You can't just return $fun->() because the return only takes you out of the eval block.
Same basic answer as Nemo, but with some improvements:
wantarray will get you the information you need.
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->(@_);
}
Void context gets propagated as void context, but that's probably acceptable. If not, it's easy to adjust.
You can do this with wantarray. (It is formatting wonky for me, too; sorry)
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;
}
I am sure a monster Perl hacker could find a way to tighten this up, but that is the basic idea.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With