【问题标题】:R specify function environmentR指定功能环境
【发布时间】:2012-09-05 10:09:42
【问题描述】:

我有一个关于 R 语言中的函数环境的问题。 我知道每次在 R 中调用一个函数,一个新的环境 E 被创建在其中执行函数体。的父链接 E 指向创建函数的环境。

我的问题:是否有可能以某种方式指定环境 E,即可以一个 提供一个特定的环境来执行函数?

【问题讨论】:

  • environment(fun) <- value 有什么问题,如?environment 中所述?
  • 您可以在全局环境之外的环境中评估函数调用,但这仍会在函数生成一个新环境,但现在该环境的父级将是您在不是全球环境中评估它的环境。会这样吗?如果是这样,请参阅?with?eval,后者是with() 使用的较低级别的函数。
  • 那么你能不能改变这个函数,以便设置你想要的调用并在指定的环境中评估它。然后你会在指定的环境中有 GlobalEnv > fun execution env > eval 调用。我不认为你可以在调用函数时停止 R 创建一个新环境,但是你可以修改函数体以在指定的环境中完成它的工作,而不是创建的那个 R(它仍然存在并且当然会被创建,在那之后你只是在改变环境。)
  • 您需要更具体地了解您想要更改的执行功能的环境。添加某个对象?更改环境变量?
  • @amonk(赏金赞助商):还请描述您期望的限制,例如。 g.:是否允许更改受影响函数的函数体,是否允许包装函数,是否允许修改执行函数的每个代码点,是否还想修改来自包的函数...

标签: r function call environment


【解决方案1】:

函数的环境可以从函数外部进行更改,但不能在函数本身内部进行更改。环境是函数的属性,可以使用environment() 检索/设置。一个函数最多有一个环境,但您可以在不同的环境中复制该函数。

让我们用 x 的值设置一些环境。

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

还有一个函数foo,它使用环境中的x

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

现在我们可以编写一个辅助函数,我们可以用它来调用任何环境下的函数。

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

这实际上返回了一个分配了不同环境的新函数(或者如果未指定,它使用调用环境),我们可以通过传递参数来调用该函数。观察

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

【讨论】:

    【解决方案2】:

    这是解决问题的另一种方法,直接取自http://adv-r.had.co.nz/Functional-programming.html

    考虑代码

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

    (已更新以提高准确性) 外部函数创建一个环境,该环境被保存为一个变量。调用这个变量(一个函数)有效地调用了内部函数,它更新了与外部函数关联的环境。 (我不想直接复制 Wickham 的整个部分,但我强烈建议任何有兴趣的人阅读标题为“可变状态”的部分。我怀疑你可能会比这更有趣。例如,这里是一个带有重置选项的修改:

    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)
    

    【讨论】:

    • 太恶心了!不过我有点喜欢
    【解决方案3】:

    我不确定我是否完全跟踪问题的目标。但是可以设置函数执行的环境,修改该环境中的对象,然后从全局环境中引用它们。这是一个说明性示例,但我不知道这是否回答了提问者的问题:

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

    导致:打印错误(a):找不到对象“a”

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

    返回:假

    e$a 
    

    返回:假

    【讨论】:

      猜你喜欢
      • 2014-06-13
      • 2015-11-10
      • 2015-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-03
      • 2020-05-27
      相关资源
      最近更新 更多