Я был заинтригован этой проблемой и попытался решить ее несколькими способами.К сожалению, они не работали.Поэтому я склонен полагать, что это не может быть сделано.... Но кто-то еще может доказать, что я не прав!
В любом случае, я решил опубликовать свои неудачные попытки, чтобы они были записаны.Я сделал их так, чтобы они печатали "ONEXIT!" после"Еще нет!"если они работали ...
1 - Во-первых, просто попробуйте оценить on.exit
в родительской среде:
f <- function() { eval(on.exit(cat('ONEXIT!\n')), parent.frame()); 42 }
g <- function() { x<-f(); cat('Not yet!\n'); x }
g() # Nope, doesn't work!
Это не сработает, возможно, потому что on.exit
Функция добавляет материал в текущий кадр стека, а не в текущую среду.
2 - Активизируйте игру и попытайтесь вернуть выражение, которое оценивается вызывающей стороной:
f <- function() { quote( {on.exit(cat('ONEXIT!\n')); 42}) }
g <- function() { x<-eval(f()); cat('Not yet!\n'); x }
g() # Nope, doesn't work!
Это неЭто тоже не работает, вероятно, потому что eval
имеет свой собственный стековый фрейм, отличный от g
.
3 - принесите мою A-игру и попробуйте положиться на ленивую оценку:
h <- function(x) sys.frame(sys.nframe())
f <- function() { h({cat('Registering\n');on.exit(cat("ONEXIT!\n"));42}) }
g <- function() { x<-f()$x; cat('Not yet!\n'); x }
g() # Worse, "ONEXIT!" is never printed...
Это возвращает окружение вызывающей стороне, и когда вызывающая сторона обращается к "x" в нем, вычисляется выражение, включающее on.exit
.... Но, похоже, on.exit
вообще не регистрируется в этом случае.
4 - Хм.Есть еще один способ, который все еще может работать: .Call
к некоторому коду C, который вызывает on.exit
.Возможно, при вызове C не будет добавлен еще один кадр стека ... Это слишком сложно для меня сейчас, чтобы проверить, но, возможно, какой-нибудь гуру RAPI / RCpp может сделать это?