R specify function environment

限于喜欢 提交于 2019-12-05 11:49:08

A function has an environment that can be changed from outside the function, but not inside the function itself. The environment is a property of the function and can be retrieved/set with environment(). A function has at most one environment, but you can make copies of that function with different environments.

Let's set up some environments with values for x.

x <- 0
a <- new.env(); a$x <- 5
b <- new.env(); b$x <- 10

and a function foo that uses x from the environment

foo <- function(a) {
    a + x
}
foo(1)
# [1] 1

Now we can write a helper function that we can use to call a function with any environment.

with_env <- function(f, e=parent.frame()) {
    stopifnot(is.function(f))
    environment(f) <- e
    f
}

This actually returns a new function with a different environment assigned (or it uses the calling environment if unspecified) and we can call that function by just passing parameters. Observe

with_env(foo, a)(1)
# [1] 6
with_env(foo, b)(1)
# [1] 11
foo(1)
# [1] 1

Here's another approach to the problem, taken directly from http://adv-r.had.co.nz/Functional-programming.html

Consider the code

new_counter <- function() {
  i <- 0
  function() {
    i <<- i + 1
    i
  }
}

(Updated to improve accuracy) The outer function creates an environment, which is saved as a variable. Calling this variable (a function) effectively calls the inner function, which updates the environment associated with the outer function. (I don't want to directly copy Wickham's entire section on this, but I strongly recommend that anyone interested read the section entitled "Mutable state". I suspect you could get fancier than this. For example, here's a modification with a reset option:

new_counter <- function() {
  i <- 0
  function(reset = FALSE) {
    if(reset) i <<- 0
    i <<- i + 1
    i
  }
}

counter_one <- new_counter()
counter_one()
counter_one()
counter_two <- new_counter()
counter_two()
counter_two()
counter_one(reset = TRUE)

I am not sure I completely track the goal of the question. But one can set the environment that a function executes in, modify the objects in that environment and then reference them from the global environment. Here is an illustrative example, but again I do not know if this answers the questioners question:

e <- new.env()
e$a <- TRUE
testFun <- function(){
  print(a)
}
testFun()

Results in: Error in print(a) : object 'a' not found

testFun2 <- function(){
  e$a <- !(a) 
  print(a)
}
environment(testFun2) <- e
testFun2()

Returns: FALSE

e$a 

Returns: FALSE

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!