[R] How to modify object's code living in some environment?

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Mon Dec 27 14:25:44 CET 2021


On 27/12/2021 8:06 a.m., Grzegorz Smoliński wrote:
> Hi,
> 
> I know it is possible to find the environment in which some object
> lives using the 'environment()' function and the name of this object,
> but how to modify code of this object after this? Below is MRE:

You are misunderstanding the relation between environments and 
functions.  However, your understanding is also being messed up by a bug 
in R, so it's not entirely your fault.

More details below:
> 
> test <- function() 1
> 
> test() # 1
> 
> environment(test)$test <- eval(parse(text = "function() 2"))

First:  while it's usually true that function f will be found in 
environment(f), these are really separate concepts.

The environment of a function is where it will start looking for 
non-local variables. It is initially the environment in which the 
function definition is evaluated.

The environment holding a function can be completely different.  This 
most commonly shows up when you have functions that create other 
functions.  For example,

   factory <- function(x) {
     force(x)
     function() print(x)
   }

   f <- factory(3)
   f()

which will print 3.  Here environment(f) is the evaluation frame of the 
call to factory(3), while f is not stored there, it is stored in the 
global environment.  (If you run ls(environment(f)) you won't see "f" 
listed, only "x".)

In your first line "test <- function() 1" you create a function named 
test in the global environment whose environment is also the global 
environment.

The third line should do what you want, i.e. put the new definition into 
the environment of the test function, using the name test, but it 
doesn't:  I think that's a bug in R.  It should be equivalent to

   .GlobalEnv$test <- eval(parse(text = "function() 2"))

or

   test <- eval(parse(text = "function() 2"))

but as you saw, it's not.  They do what you were expecting your third 
line to do.

> 
> test() # still 1
> 
> .GlobalEnv$test <- eval(parse(text = "function() 3"))
> 
> test() # 3
> 
> The context is I have shiny app which code I would like to modify (add
> something) and the only way to refer to this environment I know is to
> use 'environment()' (as I see, those functions do not live in
> .GlobalEnv), but as you can see above, I can't use it to modify the
> code.

You can, as long as you work around the bug in R.  Just change that 
third line into two statements:

   e <- environment(test)
   e$test <- eval(parse(text = "function() 2"))

Duncan Murdoch



More information about the R-help mailing list