Является ли проблемой перезапуск прерванной оценки обещания?

#r #promise #delayed-execution

#r #обещание #отложенное выполнение

Вопрос:

Используя создание обещания delayedAssign() , легко создать сценарий, который может привести к выдаче restarting interrupted promise evaluation предупреждения. Почему в таком сценарии выдается предупреждение? Указывает ли это предупреждение на «небезопасные» методы или это скорее «к вашему сведению» и может быть безопасно проигнорировано (т. Е. Приглушено)? Рассмотрим следующий пример:

 counter <- 0L

make_val <- function() {

  if (counter < 1L) {
    counter <<- counter   1L
    stop("insufficient count")
  }

  "yay!"
}

delayedAssign("foo", make_val())

foo
#> Error in make_val() : insufficient count

foo
#> [1] "yay!"
#> Warning message:
#> restarting interrupted promise evaluation

foo
#> [1] "yay!"
  

Безопасно ли отключать это предупреждение? Или перезапуск прерванной оценки обещания — это то, чего следует избегать?

 get_foo <- function() {

  mute_ripe <- function(warn) {

    if (identical(conditionMessage(warn),
                  "restarting interrupted promise evaluation")) {

      invokeRestart("muffleWarning")
    }
  }

  tryCatch(
    withCallingHandlers(get("foo", envir = .GlobalEnv), warning = mute_ripe),
    error = function(err) NULL
  )
}

counter <- 1L
delayedAssign("foo", make_val())

get_foo()
#> NULL

get_foo()
#> [1] "yay!"

get_foo()
#> [1] "yay!"

  

Ответ №1:

Я бы сохранил это предупреждающее сообщение. Рассмотрим следующий пример

 counter <- 0L

make_val <- function() {
  counter <<- counter   1L
  if (counter == 4L) {
    stop("somehow triggered an error halfway through")
  }
  counter
}

for (letter in letters[1:10]) {
    delayedAssign(letter, make_val())
}

a; b; c; d; e; f; g; h; i; j
  

Здесь я буду присваивать 1:10 переменные a-j в будущем. Каждая переменная зависит от состояния, потому что переменной будет присвоено значение тогда и только тогда, когда предыдущее присвоение будет успешно оценено (хотя это не рекомендуемая практика). Если каким-то образом ошибка возникает на полпути цепочки вычислений, то вы можете видеть, что оценка останавливается прямо там, где возникает ошибка.

 > a; b; c; d; e; f; g; h; i; j
[1] 1
[1] 2
[1] 3

Error in make_val() : somehow triggered an error halfway through
  

Однако, если вы повторно запустите код, вы можете успешно выполнить каждое задание, но вы просто получите неправильный набор результатов.

 > a; b; c; d; e; f; g; h; i; j
[1] 1
[1] 2
[1] 3
[1] 5
Warning message:
restarting interrupted promise evaluation 
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
  

Если такого предупреждающего сообщения нет, то я думаю, что существует ненулевая вероятность того, что этот набор неправильных результатов может не быть идентифицирован пользователем, поскольку назначения выполняются без ошибок, когда он / она пытается повторно запустить код для отладки.