on.exit call via eval fires before function ends

Viewed 35

Any idea why the eval implementation fires the callback before the function ends?

# on.exit fires on exit
exit_test1 = function(){
  on.exit(expr = message('close'))
  message('hello')
}
exit_test1()
#> hello
#> close

# on.exit fires before exit
exit_test2 = function(){
  eval(parse(text = "on.exit(expr = message('close'))"))
  message('hello')
}
exit_test2()
#> close
#> hello
2 Answers

This is mentioned in the documentation for eval_bare. eval does not evaluate on.exit() in the correct frame environment.

exit_test2 = function() {
  exit_cmd = quote(on.exit(expr = message('close 2')))
  message('hello')
  rlang::eval_bare(exit_cmd)
  message('hello')
}
exit_test2()
#> hello
#> hello
#> close 2

Further to @Paul's solution in fact I need a string to be executed, so this is the solution:

exit_test2 = function() {
  exit_cmd = quote(on.exit(expr = eval(parse(text="message('close')"))))
  rlang::eval_bare(exit_cmd)
  message('hello')
}
exit_test2()
#> hello
#> close
Related