Duncan Murdoch
2021-Dec-27 13:27 UTC
[R] How to modify object's code living in some environment?
On 27/12/2021 8:25 a.m., Duncan Murdoch wrote:> 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")) >And I forgot to mention, as Ivan did, that this might not do what you want, because of the difference in the concepts of "environment(f)" and "environment where f is found". Duncan Murdoch
Grzegorz SmoliĆski
2021-Dec-27 14:36 UTC
[R] How to modify object's code living in some environment?
Thank you, Ivan and Duncan. The truth is I still feel lost in this concept of environments, generally speaking. What I really thought about is the possibility to make a shiny app where there will be possible to choose the function name (from the set of all functions defined in this app / modules / other helper files sourced on the start of app) and write on the beginning of the body of this chosen function 'browser()'. I have developed an app using modules and I have found that it is not convenient to stop the app, write 'browser()' where needed, start the app and make something to run the function where is `browser()`, so I have started to think if I could write this `browser()` on demand, using the app itself (so: without stopping the app), then make something to run the function, where is 'browser()' and enabling interactive debugger. But I see now it is not good to make too many assumptions didn't knowing some topic :) pon., 27 gru 2021 o 14:27 Duncan Murdoch <murdoch.duncan at gmail.com> napisa?(a):> > On 27/12/2021 8:25 a.m., Duncan Murdoch wrote: > > 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")) > > > > And I forgot to mention, as Ivan did, that this might not do what you > want, because of the difference in the concepts of "environment(f)" and > "environment where f is found". > > Duncan Murdoch