R предупреждающее сообщение по рекурсивному выражению: Если Вы перестали работать, попробуйте, попробуйте еще раз

Я хочу создать функцию, которая повторит выражение, если это перестанет работать. Вот моя рабочая версия:

retry <- function(.FUN, max.attempts=3, sleep.seconds=1) {
  x <- NULL
  if(max.attempts > 0) {
    f <- substitute(.FUN)
    x <- try(eval(f))
    if(class(x) == "try-error") {
      Sys.sleep(sleep.seconds)
      return(suppressWarnings(retry(.FUN, max.attempts-1)))
    }
  }
  x
}

retry(stop("I'm here"))

Если я удаляю suppressWarnings() функция выше, затем я получаю ряд предупреждений на каждом рекурсивном вызове. Кто-либо знает то, что я делаю неправильно, который вызвал бы это?

Вот пример, который может неоднократно выполняться:

retry({ tmp <- function() { if(rnorm(1) < 0) stop("I'm here") else "success" }; tmp() })
5
задан Shane 30 June 2010 в 17:57
поделиться

2 ответа

Я не уверен, могу ли я точно описать причину, но я изолировал проблему и могу ее исправить. Основная проблема заключается в рекурсии: retry (.FUN, max.attempts-1) - когда рекурсивный вызов вызывает replace (.FUN) , он будет подниматься на уровень стек вызовов, чтобы выяснить, каково значение .FUN - он должен перезапустить оценку обещания (отложенное выполнение аргументов функции) на уровень выше.

Исправление - просто выполнить подстановку один раз:

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())

Чтобы создать функции, которые можно было бы гибко использовать, я настоятельно рекомендую свести к минимуму использование подстановки. По моему опыту, лучше всего иметь одну функцию, которая выполняет замену, а другая - всю работу. Это позволяет использовать функцию при вызове из другой функции:

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
8
ответ дан 18 December 2019 в 16:35
поделиться

Не уверен, почему вы получаете предупреждения ... но если использовать для цикла , они исчезнут.

retry <- function(.FUN, max.attempts=3, sleep.seconds=1) 
  {
  x <- NULL
  for (i in 1:max.attempts)
      {
      f <- substitute(.FUN)
      x <- try(eval(f))
      if (class(x) == "try-error")
         {
         Sys.sleep(sleep.seconds)
         }
       else
         {
         return (x)
         }
      }
  x
  }
4
ответ дан 18 December 2019 в 16:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: