[prev in list] [next in list] [prev in thread] [next in thread] 

List:       r-help
Subject:    Re: [R] How to modify object's code living in some environment?
From:       Duncan Murdoch <murdoch.duncan () gmail ! com>
Date:       2021-12-29 14:49:03
Message-ID: c1dbfc56-41e5-472a-37f5-cc83256bea18 () gmail ! com
[Download RAW message or body]

On 29/12/2021 9:29 a.m., Grzegorz Smoliński wrote:
> 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.

No problem, though I'd suggest posting the answer as an answer, rather 
than an edit to your question.

Duncan Murdoch

> 
> śr., 29 gru 2021 o 11:24 Duncan Murdoch <murdoch.duncan@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@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@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.
> > 
> 
> ______________________________________________
> R-help@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.

______________________________________________
R-help@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.


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic