From hb at biostat.ucsf.edu  Sun Nov  3 22:19:37 2013
From: hb at biostat.ucsf.edu (Henrik Bengtsson)
Date: Sun, 3 Nov 2013 13:19:37 -0800
Subject: [Rd] on.exit() & sys.on.exit(): Calling them via eval() does
 not work as hoped
In-Reply-To: <CAJoaRhbVstp3U_fxUH09dPFeSvuM3DU0otROWYnrYxpqwEpk-g@mail.gmail.com>
References: <CAFDcVCTsGqADPyf_MAiNmLKZofLpy-BkXGABXT6G5=kjotMQcw@mail.gmail.com>
	<CAJoaRhbVstp3U_fxUH09dPFeSvuM3DU0otROWYnrYxpqwEpk-g@mail.gmail.com>
Message-ID: <CAFDcVCSm=3kskifjomJjoGL8d0EXa-xYdiwfiBOc0PSaLMyUOg@mail.gmail.com>

On Sun, Nov 3, 2013 at 2:16 AM, Peter Meilstrup
<peter.meilstrup at gmail.com> wrote:
> eval() tends to be able to convince normal functions of where they are
> executing, but primitive functions use different methods to get their
> evaluation context and aren't as easily fooled.

Brilliant wording :)

> It turns out do.call()
> works better on primitive functions, and it will work for "on.exit".
> However I wasn't able to get 'sys.on.exit' to work.
>
> add_on_exit <- function(what) {
>   do.call("on.exit", list(substitute(what), add=TRUE), envir=parent.frame())
> }

Interesting, but also worrying at the same time.  Since these are
undocumented(*) "features" of on.exit()/sys.on.exit() and it works for
on.exit() and not sys.on.exit(), it also means that I'm not sure if I
can rely on this do.call() workaround to not break in the future.  If
would be great to hear what the R core team thinks about this.

(*) There is a small note in help("on.exit") saying "This is a
?special? primitive function: it only evaluates the argument add.".

/Henrik

>
> bar <- function() {
>   on.exit(print("exit 1"))
>   eval(quote(on.exit(print("exit 2"), add=TRUE))) #nope
>   do.call("on.exit", alist(print("exit 3"), add=TRUE))
>   add_on_exit(print("exit 4"))
>   cat("sys.on.exit():\n")
>   x <- sys.on.exit()
>   print(x)
>   cat("----- exiting\n")
> }
>
>> bar()
> [1] "exit 2"
> sys.on.exit():
> {
>     print("exit 1")
>     print("exit 3")
>     print("exit 4")
> }
> ----- exiting
> [1] "exit 1"
> [1] "exit 3"
> [1] "exit 4"
>
>
> On Sat, Nov 2, 2013 at 9:24 PM, Henrik Bengtsson <hb at biostat.ucsf.edu> wrote:
>> Why does the following eval() call on sys.on.exit() not return what I
>> expect/evaluate in the proper environment?
>>
>> foo <- function() {
>>   cat("foo()...\n");
>>   on.exit( message("exiting") )
>>
>>   cat("sys.on.exit():\n")
>>   res <- sys.on.exit()
>>   print(res)
>>
>>   cat("eval(sys.on.exit()):\n")
>>   expr <- quote(sys.on.exit())
>>   print(expr)
>>   res <- eval(expr)
>>   print(res)
>>
>>   cat("foo()...done\n")
>> }
>>
>>> foo()
>> foo()...
>> sys.on.exit():
>> message("exiting")
>> eval(sys.on.exit()):
>> sys.on.exit()
>> NULL
>> foo()...done
>> exiting
>>
>> Similar problems appear when I try to "record" on.exit() expressions
>> via eval().  It appears that the "primitives" on.exit() and
>> sys.on.exit() do something rather special.  Is there a solution to
>> what I'm trying to do?
>>
>> The reason why I'm doing this in the first place, is that I'm trying
>> to implement onExit(<expr>, where="replace"), onExit(<expr>,
>> where="last"), and onExit(<expr>, where="first").
>>
>> Thanks,
>>
>> Henrik
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel



[Rd] on.exit() & sys.on.exit(): Calling them via eval() does not work as hoped
Henrik Bengtsson