> -----Original Message----- > From: r-help-boun...@r-project.org > [mailto:r-help-boun...@r-project.org] On Behalf Of Jeff Brown > Sent: Wednesday, March 31, 2010 6:45 PM > To: r-help@r-project.org > Subject: [R] Scope and assignment: baffling > > > Hi, > > The code below creates a value, x$a, which depending on how > you access it > evaluates to its initial value, or to what it's been changed > to. The last > two lines should, I would have thought, evaluate to the same > value, but they > don't. > > f <- function () { > x <- NULL;
It would be better to say x <- list() instead of x<-NULL, since the following x$a<- coerces it to a list. > x$a <- 0; > x$get.a <- function () { > x$a; > }; > x$increment.a <- function () { > x$a <<- x$a + 5; > }; > x > }; > x <- f(); Let's make things a tad clearer by naming the output of f() 'globalX': globalX <- f() globalX is a list containing a [virtual] copy of f's x, as it stood when f() returned it. You cannot modify globalX without doing something like globalX$something<-xxx. f's x remains in the environment created when you ran f(). Each time you run f() you create an new environment (with a new version of f's x). A function's evaluation environment generally goes away when the function is done, but it remains if there are any references to the environment from f()'s return value. If the return value contains functions defined in f() then they refer to f()'s evaluation environment, so it hangs around. When you run globalX$increment.a() you are modifying f()'s environment's x$a, not globalX$a. Usually such function are written so the state variables are not in the output structure, as in: f <- function() { fA <- 0 retval <- list() retval$get.a <- function() { fA } retval$increment.a <- function() { fA <<- fA + 5 } retval } Then you can use it as you did but it is clear that retval itself doesn't contain any state. You can find the possible state variables with > globalX <- f() > globalX$increment.a() > objects(environment(globalX$get.a)) [1] "fA" "retval" > eval(quote(fA), environment(globalX$get.a)) [1] 5 > globalX$increment.a() > eval(quote(fA), environment(globalX$get.a)) [1] 10 > globalX$get.a() [1] 10 The output of objects() suggests you might want to clean up the code by not naming 'retval', just returning list(get.a=function()fA, ...). Then your environment won't carry around an unused copy of retval. Bill Dunlap Spotfire, TIBCO Software wdunlap tibco.com > x$increment.a(); > x$get.a(); > x$a; > > This can be repeated; each time you call x$increment.a(), the value > displayed by x$get.a() changes, but x$a continues to be zero. > > Is that totally weird, or what? > > Thanks, > Jeff > -- > View this message in context: > http://n4.nabble.com/Scope-and-assignment-baffling-tp1747582p1 747582.html > Sent from the R help mailing list archive at Nabble.com. > > ______________________________________________ > R-help@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. > ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.