2012-01-13 55 views
0

刷新我的問題,實現子程序的重試邏輯。使用Sub :: Attempts

Sub ::一旦發現異常(死亡),嘗試重試。 對於我來說,我希望sub在sub返回false值時重試。

請讓我知道我應該改變什麼才能使它工作?

回答

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', ...; 
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; 
    } 
} 
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; 
    } 
} 

,不使用臨時變量和until循環,您還可以使用goto &subroutine特殊形式重新啓動子:

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

goto &sub形式將拋出本地詞法變量,並重新開始的子程序,但它容易,你可能已經到@_所做的任何更改:

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

print &foo; 
__END__ 
5 

return &foo(@_)goto &foo之間的區別,在於goto版本不添加到調用堆棧 - 有點像尾遞歸優化。

0

,或者你可以我們一個簡單的while循環:

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 ; 
} 
0

如果您有關於60潛艇,你可以使用一個包裝函數(想法來自HOP被盜) - 這樣的:

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

叫 '工人' 功能(恰好沒有)像

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