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

Grzegorz Smoliński g@@mo||n@k|1 @end|ng |rom gm@||@com
Tue Dec 28 22:21:40 CET 2021


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.

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?

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?

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



More information about the R-help mailing list