Grzegorz SmoliĆski
2022-Apr-02 09:31 UTC
[R] Modificatio of function body within a function
Thank you, I think I can say that I get it, especially when reading this explanation: "assignments within a function occur *within* the function environment unless otherwise specified", so this is just like in the example below: a <- 4 fun2 <- function() { a <- 2 } fun2() a #> [1] 4 a <- 4 fun2 <- function() { env <- .GlobalEnv env$a <- 2 } fun2() a #> [1] 2 I would like to ask about one more thing, also regarding the modification of the body of function. There is one phenomenon which I'm actually using during my work with R, but I'm not sure why this happens. Below is an example of this: fun1 <- function() { 1 env <- environment(fun1) body(env$fun1) <- body(env$fun1)[-5] "one" } fun1() #> [1] "one" body(fun1) #> { #> 1 #> env <- environment(fun1) #> body(env$fun1) <- body(env$fun1)[-5] #> } Within a function, I'm removing the last line of code in that function (string "one") and what happens here is that when I use this function (first time), that string is actually returned, so this line of code which is removed is executed. I don't have a good background in computer science and would like to know why this last line of code is executed. Why not - well, I could imagine that when the function is called, it is executed line by line (of course), so before the last line ("one"), this line will be removed and this string won't be returned. However, when Bert mentioned functional paradigm, I have started to think that it may looks like this: a) function is defined b) function is called and in the one before last line of code, some object (fun1) is modified and when something is modified, the copy is made, so the modified function lives in a different memory address. c) the original function (not changed) continues computation and returns the string d) when the execution is finished, then the modified fun1 is bind to the name "fun1" and because this happens in the same environment where the original fun1 was defined and the objects are now different, garbage collector removes original (not modified) fun1 object. Is that, more or less, what happens? Best, Grzegorz pt., 1 kwi 2022 o 23:12 Bert Gunter <bgunter.4567 at gmail.com> napisa?(a):> > Heh ... These self-referential constructs are certainly puzzles... > > Does this help: > > fun1 <- function() { > 1 > body(fun1)[[2]] <<- 'one' > 'hi' > } > > > fun1 > function() { > 1 > body(fun1)[[2]] <<- 'one' ## note the double '<<" assigning to the parent env > 'hi' > } > > > fun1() > [1] "hi" > > > fun1 > function () > { > "one" ## the change was made > body(fun1)[[2]] <<- "one" > "hi" > } > > The point is that assignments within a function occur *within* the > function environment unless otherwise specified (either by <<- or the > use of the 'environment' argument in 'body<-'() ). This is, of > course, central to the functional programming paradigm of no side > effects (unless explicitly invoked). > > NOTE: Correction to this requested if this is wrong in any way!! > > Cheers, > Bert > > > > > Bert Gunter > > "The trouble with having an open mind is that people keep coming along > and sticking things into it." > -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > > Bert Gunter > > "The trouble with having an open mind is that people keep coming along > and sticking things into it." > -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > > > On Fri, Apr 1, 2022 at 12:50 PM Grzegorz Smoli?ski > <g.smolinski1 at gmail.com> wrote: > > > > Hi, > > > > I'm working on a presentation regarding the modification of the > > function body on-the-fly and just discovered something I don't > > understand. I would like to modify a body of the function within a > > function, but I see that it is possible only when explicitly referring > > to the environment where the function is defined: > > > > fun1 <- function() { > > 1 > > body(fun1)[[2]] <- "one" > > } > > fun1() > > body(fun1) > > #> { > > #> 1 > > #> body(fun1)[[2]] <- "one" > > #> } > > > > fun2 <- function() { > > 2 > > env <- environment(fun2) > > body(env$fun2)[[2]] <- "two" > > } > > fun2() > > body(fun2) > > #> { > > #> "two" > > #> env <- environment(fun2) > > #> body(env$fun2)[[2]] <- "two" > > #> } > > > > Can I get some explanation or some links / articles about this, > > please? I thought it won't be a difference and I should be able to > > modify a function body also in the first case, because I'm changing > > something in the parent environment being in the child environment. > > > > Best regards, > > > > Grzegorz > > > > ______________________________________________ > > R-help at 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.
This is not as complicated as you think. ## First define the function.> fun1 <- function() {1 env <- environment(fun1) body(env$fun1) <- body(env$fun1)[-5] "one" } ## The function as defined above is now in the environment in which it was defined, here .GlobalRnv. ## Now calling it executes **the above function.**> fun1()[1] "one" ## But this execution has the side effect of modifying the function object in .GlobalEnv. (This is why side effects can be problematic). So when we look at fun1 again in that environment, we see the modified version.> fun1function () { 1 env <- environment(fun1) body(env$fun1) <- body(env$fun1)[-5] } ## which, of course, returns nothing on being called.> fun1() >Bert Gunter "The trouble with having an open mind is that people keep coming along and sticking things into it." -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) On Sat, Apr 2, 2022 at 2:32 AM Grzegorz Smoli?ski <g.smolinski1 at gmail.com> wrote:> > Thank you, I think I can say that I get it, especially when reading > this explanation: "assignments within a function occur *within* the > function environment unless otherwise specified", so this is just like > in the example below: > > a <- 4 > fun2 <- function() { > a <- 2 > } > fun2() > a > #> [1] 4 > > a <- 4 > fun2 <- function() { > env <- .GlobalEnv > env$a <- 2 > } > fun2() > a > #> [1] 2 > > I would like to ask about one more thing, also regarding the > modification of the body of function. There is one phenomenon which > I'm actually using during my work with R, but I'm not sure why this > happens. Below is an example of this: > > fun1 <- function() { > 1 > env <- environment(fun1) > body(env$fun1) <- body(env$fun1)[-5] > "one" > } > fun1() > #> [1] "one" > body(fun1) > #> { > #> 1 > #> env <- environment(fun1) > #> body(env$fun1) <- body(env$fun1)[-5] > #> } > > Within a function, I'm removing the last line of code in that function > (string "one") and what happens here is that when I use this function > (first time), that string is actually returned, so this line of code > which is removed is executed. I don't have a good background in > computer science and would like to know why this last line of code is > executed. Why not - well, I could imagine that when the function is > called, it is executed line by line (of course), so before the last > line ("one"), this line will be removed and this string won't be > returned. However, when Bert mentioned functional paradigm, I have > started to think that it may looks like this: > a) function is defined > b) function is called and in the one before last line of code, some > object (fun1) is modified and when something is modified, the copy is > made, so the modified function lives in a different memory address. > c) the original function (not changed) continues computation and > returns the string > d) when the execution is finished, then the modified fun1 is bind to > the name "fun1" and because this happens in the same environment where > the original fun1 was defined and the objects are now different, > garbage collector removes original (not modified) fun1 object. > > Is that, more or less, what happens? > > Best, > > Grzegorz > > pt., 1 kwi 2022 o 23:12 Bert Gunter <bgunter.4567 at gmail.com> napisa?(a): > > > > Heh ... These self-referential constructs are certainly puzzles... > > > > Does this help: > > > > fun1 <- function() { > > 1 > > body(fun1)[[2]] <<- 'one' > > 'hi' > > } > > > > > fun1 > > function() { > > 1 > > body(fun1)[[2]] <<- 'one' ## note the double '<<" assigning to the parent env > > 'hi' > > } > > > > > fun1() > > [1] "hi" > > > > > fun1 > > function () > > { > > "one" ## the change was made > > body(fun1)[[2]] <<- "one" > > "hi" > > } > > > > The point is that assignments within a function occur *within* the > > function environment unless otherwise specified (either by <<- or the > > use of the 'environment' argument in 'body<-'() ). This is, of > > course, central to the functional programming paradigm of no side > > effects (unless explicitly invoked). > > > > NOTE: Correction to this requested if this is wrong in any way!! > > > > Cheers, > > Bert > > > > > > > > > > Bert Gunter > > > > "The trouble with having an open mind is that people keep coming along > > and sticking things into it." > > -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > > > > Bert Gunter > > > > "The trouble with having an open mind is that people keep coming along > > and sticking things into it." > > -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) > > > > > > On Fri, Apr 1, 2022 at 12:50 PM Grzegorz Smoli?ski > > <g.smolinski1 at gmail.com> wrote: > > > > > > Hi, > > > > > > I'm working on a presentation regarding the modification of the > > > function body on-the-fly and just discovered something I don't > > > understand. I would like to modify a body of the function within a > > > function, but I see that it is possible only when explicitly referring > > > to the environment where the function is defined: > > > > > > fun1 <- function() { > > > 1 > > > body(fun1)[[2]] <- "one" > > > } > > > fun1() > > > body(fun1) > > > #> { > > > #> 1 > > > #> body(fun1)[[2]] <- "one" > > > #> } > > > > > > fun2 <- function() { > > > 2 > > > env <- environment(fun2) > > > body(env$fun2)[[2]] <- "two" > > > } > > > fun2() > > > body(fun2) > > > #> { > > > #> "two" > > > #> env <- environment(fun2) > > > #> body(env$fun2)[[2]] <- "two" > > > #> } > > > > > > Can I get some explanation or some links / articles about this, > > > please? I thought it won't be a difference and I should be able to > > > modify a function body also in the first case, because I'm changing > > > something in the parent environment being in the child environment. > > > > > > Best regards, > > > > > > Grzegorz > > > > > > ______________________________________________ > > > R-help at 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 at 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.