Dear R users, I am running R-2.15.1 in Linux Slackware64-14.0. Here is my minimal working example: testfun <- function (x) { a <- 0; sapply(X="a", FUN=get, envir=sys.frame(which=x)); } Inside R, that is R called from within a Linux terminal, the following code works: testfun(x=5) print(testfun(x=6)) But within rkward the above code fails and the following works: testfun(x=1) print(testfun(x=2)) As you can see, the number of contexts up the call stack that contain the variable "a" varies depending on the implementation. If I call testfun() from within print(), I have to go one context up the call stack than if I call testfun() alone by itself. This implies some inherent instability of my code. Actually I need to provide get() access to the calling environment of sapply(). According to the documentation of parent.frame(), "The parent frame of a function evaluation is the environment in which the function was called". I tried to use parent.frame() instead of sys.frame() above, but the variable "a" is never found, regardless of what value I give to the parameter "n" of parent.frame(). I have basically three questions: 1. Do You have an idea how I could implement the code more stably, so that the variable "a" is always visible to get, regardless of whether testfun is used alone by itself or called from within another function? 2. Why does the implementation with parent.frame() not work? 3. Why does the number of contexts in the call stack differ in R and in rkward? It seems that when R is called from within the Linux terminal the call stack contains 4 contexts more that it does when is called from rkward. This also points to the instability of the code which I would like to solve. Any suggestions on any on the above questions will be greatly appreciated. Best regards, Martin
On Sun, Oct 7, 2012 at 10:16 AM, Martin Ivanov <tramni at abv.bg> wrote:> Dear R users, > > I am running R-2.15.1 in Linux Slackware64-14.0. Here is my minimal working example: > > testfun <- function (x) { > a <- 0; > sapply(X="a", FUN=get, envir=sys.frame(which=x)); > } > > Inside R, that is R called from within a Linux terminal, the following code works: > testfun(x=5) > print(testfun(x=6)) > But within rkward the above code fails and the following works: > testfun(x=1) > print(testfun(x=2)) > > As you can see, the number of contexts up the call stack that contain the variable "a" > varies depending on the implementation. If I call testfun() from within print(), I have to go > one context up the call stack than if I call testfun() alone by itself. This implies > some inherent instability of my code.Unlike you, I don't get testfun(x = 5) to work in a terminal emulator. As expected, I only get x =1 and print(... x = 2) to work and I just tried this with R 2.15.0 and R devel, both in Terminal and by way of ESS. It could be a buglet introduced later into the 2.15 branch, but that seems unlikely. As expected,> testfun(5)Error in sys.frame(which = x) : not that many frames on the stack Can someone else confirm the behavior you see? Cheers, Michael
Thank You very much for Your replies. Dear Michael, "Does this persist after a new session (perhaps running as R --vanilla) and/or reinstall?" Yes, it does. After running R --vanilla, still there are 4 contexts more on the call stack. "You didn't show us how you tried to use parent.frame()" I did it like this: testfun1 <- function (x1) { a1 <- 1; sapply(X="a1", FUN=get, envir=parent.frame(x1)); } testfun1(x1=1); The above code never succeeds no matter what a number I give to x1. " 3. Why does the number of contexts in the call stack differ in R and in rkward? It shouldn't. This is an issue that needs further sorting out." Here is some more info on my setup: sessionInfo() R version 2.15.1 (2012-06-22) Platform: x86_64-slackware-linux-gnu (64-bit) locale: [1] LC_CTYPE=en_US LC_NUMERIC=C LC_TIME=en_US [4] LC_COLLATE=C LC_MONETARY=en_US LC_MESSAGES=en_US [7] LC_PAPER=C LC_NAME=C LC_ADDRESS=C [10] LC_TELEPHONE=C LC_MEASUREMENT=en_US LC_IDENTIFICATION=C attached base packages: [1] stats graphics grDevices utils datasets methods base loaded via a namespace (and not attached): [1] tools_2.15.1 Best regards, Martin
Dear Prof. Lumley, Thank You very much for Your reply. I implemented Your idea not to directly call get from sapply, but inside a function, supplied to sapply. In this way the 3-rd parent frame is always the "correct" one, no matter whether I invoke testfun2() all by itself or inside another function. So my code is finally stable. It is quite tricky that when I call get() directly from sapply(), like this: sapply(X=, FUN=get, envir=parent.frame()), actually envir is an argument not to get, but to sapply, so it is evaluated in the environment of the caller, i.e. in the environment of testfun1, whose parent is the workspace, which of course does not contain the variables in the body of testfun1. In testfun2() sapply() calls get() from within a function and the envir argument to get() is supplied directly to it, i.e. it is evaluated in the environment of get(). Its first parent is the environment of the function calling get(), its second parent is the environment of sapply() and its third parent is the environment of testfun2(), which I need. That is why testfun2() works. I hope I have correctly understood this matter. Please correct me if I am wrong. Nevertheless the code is finally stable and it is thanks to Your suggestion. Best regards, Martin Ivanov >-------- ?????????? ????? -------- >??: Thomas Lumley >???????: Re: [R] get: problem with environments >??: R. Michael Weylandt >????????? ??: ?????????, 2012, ???????? 11 01:52:14 EEST > > >On Thu, Oct 11, 2012 at 11:18 AM, R. Michael Weylandt > wrote: > >> Thanks Prof Lumley, >> >> I'm still not sure how this gets to the call stack of 5 or 6 the OP >> reported or the difference between GUI & Terminal. Any thoughts there? > >I don't see how the terminal version is getting 5 and 6 rather than 1 >and 2, but my testfun2() lets the OP do what he was originally trying >to do. > >The difference between testfun() and print(testfun()) (ie, 1 vs 2, or >5 vs 6) is because of lazy evaluation: in print(testfun()), testfun() >is called from inside print() when it needs the value to do method >dispatch. > >I can't reproduce the value of 5, so I can't help much. For anyone >wanting to experiment further, it would probably be simpler to use > >testfun<-function() sys.nframe() > >rather than looking at whether a variable is found or not. I can't >see how testfun() typed at the global command prompt can return >anything other than 1, but maybe something is getting in between the >console and the evaluator. For example: >> testfun() >[1] 1 >> print(testfun()) >[1] 2 >> capture.output(testfun()) >[1] "[1] 6" > >I don't see why a pure console program should do this on Linux, though. > > -thomas > > >-- >Thomas Lumley >Professor of Biostatistics >University of Auckland >
Possibly Parallel Threads
- apply function across two variables by mult factors
- Passing on "groups" argument to xyplot within a plotting function
- Different serialization of functions in interactive vs. batch mode
- Different serialization of functions in interactive vs. batch mode
- Special characters in Rd example section will cause errors