Изменение списка выражений on.exit

Я думаю, что нет, но можно ли отменить звонок, зарегистрированный с on.exit?

Например, с учетом задачи, требующей быстрой очистки:

myfunc <- function(...) {
  prep_for_messy_stuff
  on.exit(cleanup_messy_stuff(), add = TRUE)
  messy_stuff
  cleanup_messy_stuff()
  # do other work that requires non-messiness
}

Если cleanup_messy_command() будет привередливым, тогда он будет жаловаться, когда будет запущен в конце (его второй экземпляр). (Предположим, что мы не контролируем эту функцию очистки. tryCatch(capture.output(suppressMessages(cleanup_messy_stuff())), warning=function(w) FALSE, error=function(e) FALSE) не желательно.)

Без особой работы я могу получить текущий список выражений, удалить одно (или несколько) и заменить on.exit список выражений:

myfunc <- function(...) {
  on.exit(0) # to ensure list(ex) is always a list of expressions, leading with "{"
  prep_for_messy_stuff
  on.exit(cleanup_messy_stuff(), add = TRUE)
  messy_stuff
  cleanup_messy_stuff()
  ex <- sys.on.exit() # if I get here, there's no need to cleanup again
  do.call(on.exit, c(list(ex[ -length(ex) ]), add = FALSE))
  # do other work that requires non-messiness
}

Начальный on.exit вызов так, что length(ex) всегда один плюс количество выражений, ака можно рассматривать как list; в противном случае это длина первого выражения (не 1). (Первая в этом списке - открывающая скобка { блока выражений.)

Этот метод, кажется, работает, но мне интересно, начинаю ли я гадить с внутренностями, когда делаю это таким образом. Если мне нужно удалить что-либо, кроме последнего выражения в списке, то я думаю, что могу предположить, что (n+1) элемент взят из n-го вызова on.exit,

Вопросы:

  1. Когда эта техника потерпит неудачу?
  2. Есть ли более разумный / эффективный метод для решения этой ситуации?
  3. (Список пожеланий) Есть ли способ безопасно выбрать определенные записи? (например, по имени, по уникальному ключу). (Другие языки предоставляют ссылку для добавления перехвата, который можно использовать для отмены перехвата, установленного вызывающей стороной или возвращенного on.exit.)

Рабочий пример

Рабочий пример с не псевдокодом:

myfunc <- function(...) {
  on.exit(0) # to ensure list(ex) is always a list of expressions, leading with "{"
  on.exit(message('a'), add = TRUE)
  on.exit(message('b'), add = TRUE)
  on.exit(message('c'), add = TRUE)
  ex <- sys.on.exit()
  do.call(on.exit, c(list(ex[ -length(ex) ]), add = FALSE))
  # remaining stuff
  99
}
myfunc()
# a
# b
# [1] 99

Предостережение: в большинстве случаев вполне нормально подождать до конца функции, чтобы сработали выражения очистки. Это предназначено для тех случаев, когда быстрая очистка предпочтительна / необходима (например, для длительных процессов).

0 ответов

Другие вопросы по тегам