Tôi không chắc liệu mình có thể mô tả chính xác nguyên nhân hay không, nhưng tôi đã phân lập được sự cố và có thể khắc phục sự cố. Vấn đề cơ bản là đệ quy: retry(.FUN, max.attempts-1)
- khi cuộc gọi đệ quy gọi substitute(.FUN)
nó sẽ tăng lên một mức của ngăn xếp cuộc gọi để tìm ra giá trị của .FUN
là - nó phải khởi động lại việc đánh giá lời hứa (thực thi chậm trễ của các đối số hàm) lên cấp.
Một sửa chữa là chỉ cần làm việc thay thế một lần:
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())
Để tạo các chức năng mà bạn có thể sử dụng linh hoạt, tôi khuyên bạn nên giảm thiểu việc sử dụng thay thế. Theo kinh nghiệm của tôi, bạn thường tốt nhất có một chức năng thay thế, và một chức năng khác làm tất cả công việc. Điều này giúp bạn có thể sử dụng chức năng khi được gọi từ một chức năng khác:
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
Tôi đã nghĩ rằng việc thực thi đệ quy của .UN trong phiên bản của bạn sẽ không hoạt động vì .FUN đã được đánh giá tại thời điểm đó? Tôi sẽ kiểm tra nó ... – Shane
Tôi nghĩ rằng bạn đã đúng, nhưng trong khi chờ đợi tôi đã tìm ra. Tôi nghĩ rằng f của tôi là một ví dụ tốt hơn bởi vì đôi khi nó lỗi và đôi khi nó không. Chạy nó một vài lần để kiểm tra xem nó có làm những gì bạn mong đợi không. Tôi không chắc chắn những gì bạn muốn nó trở lại khi bạn hết nỗ lực nhưng vẫn có một lỗi. – hadley
Ồ, tôi thấy bạn có số điểm tương đương với số f của tôi ở cuối bài đăng của bạn:/ – hadley