Is restarting an interrupted promise evaluation a problem?

5.5k Views Asked by At

Creating a promise using delayedAssign(), it is easy to construct a scenario which might lead to the emission of a restarting interrupted promise evaluation warning. Why is a warning thrown in such a scenario? Does this warning indicate "unsafe" practices or is this more of an "fyi" and can safely be ignored (i.e. muffled)? Consider the following example:

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!"

Is it safe to silence this warning? Or is restarting an interrupted promise evaluation something that should be avoided?

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

There are 1 best solutions below

0
On

I would keep that warning message. Consider the following example

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

Here, I will assign 1:10 to variables a-j in the future. Each variable is state-dependent because a value will be assigned to a variable if and only if the previous assignment is successfully evaluated (not a recommended practice though). If somehow an error occurs halfway through the evaluation chain, then you can see that the evaluation stops right at where the error occurs.

> 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

However, if you rerun the code, then you can get every assignment done successfully, but you just get a wrong set of results.

> 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

If there is no such warning message, then I think there is a non-zero chance that this set of wrong results may not be identified by the user because assignments are error-free when he/she attempts to rerun the code to debug.