Ich bin nicht sicher, ob ich die Ursache genau beschreiben kann, aber ich habe das Problem isoliert und kann es beheben. Das Grundproblem ist die Rekursion: retry(.FUN, max.attempts-1)
- wenn der rekursive Aufruf substitute(.FUN)
aufruft, wird es eine Ebene des Aufruf-Stacks gehen, um herauszufinden, was der Wert .FUN
ist - es muss die Bewertung eines Versprechens (die verzögerte Ausführung) neu starten von Funktionsargumenten) eine Ebene höher.
Ein Fix ist nur einmal die Auswechslung tun:
retry <- function(.FUN, max.attempts = 3, sleep.seconds = 0.5) {
expr <- substitute(.FUN)
retry_expr(expr, max.attempts, sleep.seconds)
}
retry_expr <- function(expr, max.attempts = 3, sleep.seconds = 0.5) {
x <- try(eval(expr))
if(inherits(x, "try-error") && max.attempts > 0) {
Sys.sleep(sleep.seconds)
return(retry_expr(expr, max.attempts - 1))
}
x
}
f <- function() {
x <- runif(1)
if (x < 0.5) stop("Error!") else x
}
retry(f())
Funktionen erstellen, die Sie flexibel nutzen können, empfehle ich die Verwendung von Ersatz zu minimieren. Meiner Erfahrung nach ist es normalerweise am besten, wenn Sie eine Funktion haben, die die Substitution durchführt, und eine andere, die die ganze Arbeit erledigt. Dies ermöglicht es, die Funktion zu verwenden, wenn sie von einer anderen Funktion aufgerufen wird:
g1 <- function(fun) {
message("Function starts")
x <- retry(fun)
message("Function ends")
x
}
g1(f())
# Function starts
# Error in eval(expr, envir, enclos) : object 'fun' not found
# Error in eval(expr, envir, enclos) : object 'fun' not found
# Error in eval(expr, envir, enclos) : object 'fun' not found
# Error in eval(expr, envir, enclos) : object 'fun' not found
# Function ends
g2 <- function(fun) {
message("Function starts")
expr <- substitute(fun)
x <- retry_expr(expr)
message("Function ends")
x
}
g2(f())
# Function starts
# Error in f() : Error!
# Function ends
# [1] 0.8079241
Ich hätte gedacht, dass die rekursive Ausführung von .FUN in Ihrer Version nicht funktionieren würde, weil .FUN an diesem Punkt bereits ausgewertet worden wäre? Ich werde es testen ... – Shane
Ich denke, du hast Recht, aber in der Zwischenzeit habe ich es herausgefunden. Ich denke, mein f ist ein besseres Beispiel, weil es manchmal Fehler macht und manchmal nicht. Führen Sie es ein paar Mal aus, um zu überprüfen, ob es Ihren Erwartungen entspricht. Ich bin nicht sicher, was Sie wollten, dass es zurückkehrt, wenn Sie keine Versuche mehr haben, aber immer noch einen Fehler haben. – hadley
Oh, ich sehe, Sie hatten ein Äquivalent zu meinem f in der Unterseite Ihres Beitrags:/ – hadley