使用Sub :: Attempts实现子例程的重试逻辑

时间:2012-01-13 21:21:54

标签: perl

刷新我的问题。

Sub :: Attempts一旦找到异常(die)就重试。 对我来说,当sub返回false值时,我希望sub重试。

请让我知道我应该改变什么才能让它发挥作用?

5 个答案:

答案 0 :(得分:1)

如果你想使用Sub::Attempts,只需创建一个子程序来修改你必须使其死亡的子程序,而不是返回false:

sub die_on_failure {
    my $name = (caller).'::'.shift;
    my $glob = do {no strict 'refs'; \*$name};

    my $code = \&$glob;
    no warnings 'redefine';
    *$glob = sub {
        my $ret = &$code;
        $ret ? $ret : die "$name failed"
    }
}

然后就这样做:

die_on_failure 'your_sub_name';

致电之前:

attempts 'your_sub_name', ...;

答案 1 :(得分:0)

sub retryBeforeFail {
  my $className = shift;
  my $attempt = shift;
  my $max = shift;
  my $success = 0;

  ... main code here ...

  if (!$success && $attempt < $max) {
   $attempt++;
   return $self->retryBeforeFail($attempt, $max);
  } else {
   return $success;
  }
}

答案 2 :(得分:0)

听起来你需要一个循环,某种形式。解决这个问题的一种方法是简单的“全部完成”标志:

sub foo {
   my $success = undef;
   until ($success) {
       # do something interesting
       redo if $something_failed;
       # do more things here
       ++$success; # if it all worked properly
       # or, exit early on success:
       return $something if $all_is_well;
   }
}

如果不使用临时var和until循环,您还可以使用goto &subroutine的特殊形式重新启动子资源:

sub foo {
   # do something interesting
   if ($something_failed) {
        goto &foo;
   }
}

goto &sub表单将抛出本地词法变量,并重新启动子例程,但 容易受到@_所做的任何更改:< / p>

sub foo {
   my $x = shift @_;
   if ($x < 5) {
       @_ = ($x + 1);
       goto &foo;
   }
   return $x;
}

print &foo;
__END__
5

return &foo(@_)goto &foo之间的区别在于goto版本没有添加到调用堆栈 - 有点像尾递归优化。

答案 3 :(得分:0)

或者你可以让我们一个简单的循环:

sub retry_before_fail {
  my ( $maxtries , $coderef , @args ) = @_ ;
  while( $maxtries ) {
    # $coderef returns non zero upon success
    if( my $result = $coderef->( @args ) ) {
      return $result ;
    }
    $maxtries-- ;
  }
  # Failure now either return or die
  return ;
}

答案 4 :(得分:0)

如果你有大约60个潜艇,你可以使用包装器功能(从HOP偷来的想法) - 就像这样:

sub rpw {
  my $f = shift;
  my $t = shift;
  my $r = &$f(@_);
  while ('fail' eq $r && --$t) {
    $r = &$f(@_);
  }
  return $r;
}

调用'worker'函数(不完全像)

sub s00 {
  my $r = 0.2 > rand() ? 'ok' : 'fail';
  print '  in s00 => ', join( '-', @_, $r), "\n";
  return $r;
}

sub s01 {
  my $r = 0.5 < rand() ? 'ok' : 'fail';
  print '  in s01 => ', join( '-', @_, $r), "\n";
  return $r;
}

来自主要代码,如

  print 'from s00 => ', s00(1, 2, 3), "\n";
  print 'from s01 => ', s01(qw/a b/), "\n";

  print 'from rpw => ', rpw(\&s00, 5, 1, 2, 3), "\n";
  print 'from rpw => ', rpw(\&s01, 5, qw/a b/), "\n";

输出(不幸运):

  in s00 => 1-2-3-fail
from s00 => fail
  in s01 => a-b-fail
from s01 => fail
  in s00 => 1-2-3-fail
  in s00 => 1-2-3-fail
  in s00 => 1-2-3-fail
  in s00 => 1-2-3-fail
  in s00 => 1-2-3-fail
from rpw => fail
  in s01 => a-b-fail
  in s01 => a-b-ok
from rpw => ok
运气不错:

  in s00 => 1-2-3-ok
from s00 => ok
  in s01 => a-b-fail
from s01 => fail
  in s00 => 1-2-3-fail
  in s00 => 1-2-3-fail
  in s00 => 1-2-3-fail
  in s00 => 1-2-3-ok
from rpw => ok
  in s01 => a-b-fail
  in s01 => a-b-fail
  in s01 => a-b-ok
from rpw => ok