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

Grzegorz Smoliński g@@mo||n@k|1 @end|ng |rom gm@||@com
Wed Dec 29 15:29:02 CET 2021


Thank you. I posted this question on SO in the meantime as well, but
there is no answer for my question, so I pasted your answer
(https://stackoverflow.com/questions/70517625/how-to-use-trace-for-function-in-parent-or-child-environment).
Hope it is fine for you.

śr., 29 gru 2021 o 11:24 Duncan Murdoch <murdoch.duncan using gmail.com> napisał(a):
>
> On 28/12/2021 4:21 p.m., Grzegorz Smoliński wrote:
> > Thank you for all the comments. If this is not a problem, I would like
> > to continue this thread as for me a lot of questions are still open.
> > But if I should post other questions in different messages / topics,
> > please let me know.
> >
> > I didn’t answer Ivan’s question previously, but yes, my desired result
> > is indeed what debug() / debugonce() does and Ivan mentioned trace()
> > earlier also, so I have tried this. I thought that trace() will be
> > better in my case (than debug()) since I would like to be able to call
> > trace() from one environment and insert browser() (using trace()) to
> > the function defined in parent environment (still not sure if I
> > understand this concept of environments).
> >
> > Even if I would like to use it in an shiny app, I have started with
> > this example:
> >
> > ------------------------------
> >
> > fun1 <- function() {
> >    a <-  1
> >    a
> > }
> >
> > fun2 <- function() {
> >    fun1 <- function(){
> >      b <- 2
> >      b
> >    }
> >    trace(fun1, browser, where = globalenv())
> > }
> >
> > fun1()
> > fun2()
> > fun1()
> >
> > --------------------------------
> >
> > So I was hoping to use trace inside child environment of global env,
> > i.e. set browser() using trace() to the body of function defined in
> > parent environment, but for sure I do not understand this since
> > trace() in my example above is putting the browser() function inside
> > fun1() function defined not in global environment, but in the body of
> > fun2(). I.e. I'm starting to browse the fun1() function with the local
> > variable 'b', not 'a' as I wanted.
>
> You are being bitten by normal R scoping.  While fun2 is executing, as
> soon as it executes the fun1 assignment the name fun1 is bound to the
> local function, so when you use fun1 in the first argument to trace(),
> you get that one.  It will ignore then "where" argument because it was
> passed a function object.  If you quote the name it will have to do a
> lookup and it will use "where".  So write fun2 like this:
>
> fun2 <- function() {
>    fun1 <- function(){
>      b <- 2
>      b
>    }
>    trace("fun1", browser, where = globalenv())
> }
>
>
> >
> > Can I ask for help with this? In other words, how can I refer to some
> > function from the parent environment (not necessarily defined in the
> > global environment) being in the child environment?
>
> You could have used parent.frame() in place of globalenv() if you want a
> function that was visible to the caller of fun2.  If you want a function
> that was defined with the same environment as fun2, you can usually use
> environment(fun2), or parent.env(environment()).
>
>
> >
> > Also, if I could ask - is the reversed operation possible? I mean -
> > can I refer to some function from the child environment being in the
> > parent environment? I guess not, because of ephemerality?
>
> Sometimes you can, but not usually.  If fun2 had returned a value that
> referenced the evaluation frame, you would be able to see the "b"
> version of fun1 there.  But yours didn't.  This one would:
>
>
> fun2 <- function() {
>    fun1 <- function(){
>      b <- 2
>      b
>    }
>    trace("fun1", browser, where = globalenv())
>    environment()
> }
>
> Now if you do e <- fun2(), you'll set the trace on the global fun1, but
> e$fun1 will be the local one.
>
> I don't really know how Shiny sets things up, so I can't help with the
> stuff below.
>
> Duncan Murdoch
>
>
> >
> > As I mentioned, I'm thinking about all of this in the context of shiny
> > app and the shiny app which consists of multiple files, modules. I'm
> > thinking if I could refer to any function from any environment (or at
> > least to any function in any parent environment) from one place (one,
> > current environment) where I will call debug() or trace() to insert
> > browser() at the beginning of this chosen function. And by "any
> > function" I'm thinking about another thing problematic for me. If I
> > consider this example:
> >
> > -------------------------------
> > mod.R inside R/
> > ---
> >
> > mod_UI <- function(id) {
> > }
> >
> > name_mod <- function(input, output, session) {
> >    fun1 <- reactive({
> >      a  <-  1
> >    })
> > }
> >
> > ---
> > app.R
> > ---
> >
> > library(shiny)
> >
> > ui <- fluidPage(
> >    mod_UI("mod"),
> >    textOutput("env")
> > )
> >
> > server <- function(input, output, session) {
> >
> >    name_mod("mod")
> >
> >    output$env <- renderPrint({
> >      names(environment(name_mod))
> >    })
> >
> >    observe({
> >      #trace(fun1, browser, where = environment(name_mod))
> >    })
> > }
> >
> > shinyApp(ui, server)
> > ---------------------------------------
> > I tried to refer to the fun1 in environment(name_mod) - if I'm not
> > wrong, this is my parent environment, where objects "mod_UI" and
> > "name_mod" exist, but obviously I'm doing this wrong, right? Because
> > here: "#trace(fun1, browser, where = environment(name_mod))" I have
> > tried to refer to the module environment, but I should refer to the
> > environment inside "name_mod". I don't know how to do this and here I
> > also would like to ask for help.
> >
> > I know this may not be the best place for questions regarding shiny,
> > but I think these questions are purely linked to environment topics.
> >
> > I also remember Bert's post about "body()" and yes, this seems to be a
> > better idea than my first try in my first post, but "trace()" and
> > "debug()" seem much easier as all I want is to insert browser(). But I
> > just can't get it, how to refer to functions in (any) other
> > environments.
> >
> > Thank you very much for all your help and I hope it is OK to keep asking :).
> >
> > pon., 27 gru 2021 o 18:28 Duncan Murdoch <murdoch.duncan using 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.
> >>
> >> Actually this isn't a bug in R, it is working as documented.  For a
> >> detailed explanation, see the response to my bug report here:
> >> https://bugs.r-project.org/show_bug.cgi?id=18269 .
> >>
> >> For a quick idea:  "complex assignments" are assignments where there is
> >> a complex expression on the left hand side, e.g.
> >>
> >>     environment(test)$test <- ...
> >>
> >> The way these are documented to work (in the R Language Definition
> >> manual) makes intuitive sense when you are working with regular R
> >> objects, but environments are "mutable" objects:  assigning them to a
> >> new name doesn't make a new copy, just a new reference.  That causes the
> >> definition of the complex assignment above to work in an unintuitive way.
> >>
> >> Conclusion:  you should avoid using calls like environment(f) on the
> >> left hand side of assignments, especially as part of a larger
> >> expression.  Break up the statement into steps like I did below:
> >>
> >>>      e <- environment(test)
> >>>      e$test <- eval(parse(text = "function() 2"))
> >>
> >> The same advice would apply to a function that returned an R6 object or
> >> a mutable object from the methods package (which are really environments
> >> in disguise), as well as some other exotic objects.
> >>
> >> Duncan Murdoch
> >
> > ______________________________________________
> > R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> > 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.
>



More information about the R-help mailing list