Home > Enterprise >  R: Could I make the execution environment of a function permanent?
R: Could I make the execution environment of a function permanent?

Time:11-22

I'm studying R environments but I have got a question reading the "Advanced R" book by Hadley Wickham. Is it possible to make the execution environment of a function permanent?

I will try to explain the why of my question.

When Wickham explains how the execution environment of a function works the following example is shown:

j <- function() {
    if (!exists("a")) {
         a <- 1
    } else {
         a <- a   1
    }
    print(a)
}
j()

I have understood why every time the function j gets called the returned value is 1. In another part of the text he says:

When you create a function inside another function, the enclosing environment of the child function is the execution environment of the parent, and the execution environment is no longer ephemeral.

So I have thought to create the following function:

j <- function() {
    if (!exists("a")) {
        a <- 1
    } else {
        a <- a   1
    }
    print(a)
    g <- function() {}
    g()
}
j()

But the returned value is always 1, so I suppose it's because the execution environment continues to be destroyed every time. What does that "no longer ephemeral" mean?

CodePudding user response:

Based on the book there is also possible to use function factory structure (a function that creates another function) to capture the ephemeral execution environment of the first function. The following example is just a simple way of how we could capture it:

j <- function() {
  a <- 1
  k <- function() {
    if (!exists("a")) {
      a <- 1
    } else {
      a <- a   1
    }
    print(a)
  }
}

plus <- j()
plus

<environment: 000001CAA8EAC418>
parent: <environment: global>
bindings:
 * k: <fn>
 * a: <dbl>

Now no matter how many times you use the function plus, its environment will always be the then execution environment of the first function:

library(rlang)

env_print(plus)
<environment: 000001CAA8EAC418>
parent: <environment: global>
bindings:
 * k: <fn>
 * a: <dbl>

plus()
[1] 2

env_print(plus)
<environment: 000001CAA8EAC418>
parent: <environment: global>
bindings:
 * k: <fn>
 * a: <dbl>

I hope this to some extent answer your question, however there might be better answers out there too.

CodePudding user response:

A permanent environment within a function is called a "closure". Here a toy example to demonstrate this. Check it out and then modify your code accordingly.

closure <- function(j) {
  i <- 1
  function(x) {
    i <<- i   1
    j * i   x
  }
}

i <- 12345
instance <- closure(11)

instance(3)
#[1] 25

instance(3)
#[1] 36

instance(3)
#[1] 47

otherObj <- closure(2)
otherObj(3)
#[1] 7

instance(2)
#[1] 57

PS: Please use always proper indentation to improve readability of code.

  •  Tags:  
  • r
  • Related