【问题标题】:Accessing the execution environment of a function in R访问 R 中函数的执行环境
【发布时间】:2017-02-06 09:26:25
【问题描述】:

我有一个为程序的其余部分“准备”东西的功能。例如,下面的函数定义了两个函数:

prepare = function() {
    f = function(x) x+1
    g = function(x) x+2
}

当然,一旦函数执行,函数 f 和 g 将不再可用。它们在“prepare”的执行环境中定义,一旦函数完成执行,它就消失了。

我的问题是,有没有办法保留或访问该执行环境?

场景是我从外部获得“准备”功能,因此无法编辑其代码,我想执行它并以下列方式使用它所做的任何事情:

my_function = function(prepare) {
    # the prepare function is supplied by the user
    prepare()  #this should define the f and g functions as above
    f(3)   # this wouldn't work normally, since f is defined inside prepare
}

有没有办法做到这一点?也就是说,让“准备”影响调用环境,而不是它的执行环境?

编辑:

找到了一种使用 body() 的解决方法,它允许访问函数内部的表达式,并从中构建新的表达式,因此我基于“准备”函数的“主体”和“原创”功能。正如我所想的那样,真正的解决方案是使用“方面方向”。但不幸的是,R 不是面向方面的语言。也许是一个新包的想法:-)

【问题讨论】:

    标签: r function environment execution


    【解决方案1】:

    如果你稍微修改prepare函数:

    prepare = function() {
        f = function(x) x+1
        g = function(x) x+2
        return(list(f,g))
    }
    

    你可以像这样访问函数:

    prepare()[[1]](25)
    
    # [1] 26
    

    或者你可以使用<<-,将函数放到全局环境中:

    prepare = function() {
         f <<- function(x) x+1
         g <<- function(x) x+2
     }
    

    【讨论】:

    • 很遗憾,我无法更改由其他人提供并作为参数传递的“准备”功能。
    【解决方案2】:
    >prepare<-function() return(list(f=function(x) x+1, g=function(x) x+2))
    > p<-prepare()
    > p$f(1)
    [1] 2
    > p$g(1)
    [1] 3
    

    隔了很久再编辑

    我必须自己回到这个问题上……

    > prepare
    function(x) { p = function(x) 5*x; q= function(x) x^2 }
    > with( new.env ( eval( parse(text=deparse(body(prepare))) ) ) , { print(p(5)); print(q(2))} )
    [1] 25
    [1] 4
    

    【讨论】:

    • 正如我所说 - 我无法编辑“准备”功能。它是由其他人编写的,并作为参数提供给我的代码。所以你的建议不适用。
    • 您如何确保其他人的函数中有fg?以同样的方式,您可以要求他们返回列表或更改范围,或者..将fg写入单独的文件,然后您可以调用myEnv&lt;-new.env(); source(fileName, local=myEnv)并通过myEnv$f访问它
    • 查看我的编辑。最终我找到了使用 body() 的解决方法。在我的场景中,由用户来提供“准备”功能以及稍后在代码中使用它的方式,但是代码必须在我创建的环境中执行(并向其中添加更多超出用户的控制)。
    【解决方案3】:

    利用environment(fun) 返回函数的封闭环境这一事实——它定义了函数如何查找对象——,下面使用environment() 允许您访问在prepare() 中定义的函数:

    prepare = function() {
      f = function(x) x+1
      g = function(x) x+2
    }
    
    my_function = function(preparefun) {
      # We call the prepare() function supplied by the user
      # that defines functions f() and g() and store its returned value
      # (WHICH IS A FUNCTION)
      fun_returned_by_prepare = preparefun()
      cat("Result of calling function f(3) defined in function prepare():", environment(fun_returned_by_prepare)$f(3), "\n")
      cat("Result of calling function g(3) defined in function prepare():", environment(fun_returned_by_prepare)$g(3), "\n")
    }
    
    my_function(prepare)
    

    产生:

    Result of calling function f(3) defined in function prepare(): 4 
    Result of calling function g(3) defined in function prepare(): 5
    

    但是,这只是因为 prepare() 函数返回一个函数(在这种情况下,函数 g() 定义在 prepare() 的最后一行因此返回),这意味着对prepare()fun_returned_by_prepare)返回的对象的environment()调用检索了prepare()中定义的函数g()的封闭环境,这种情况发生成为prepare()的执行环境!

    如果prepare()的返回值不是一个函数,上面的代码就不再起作用了。

    附带说明一下,如果以下内容对您可能拥有的其他应用程序很方便:我编写了一个名为 envnames 的包,除其他外,它允许您通过函数名称检索函数的执行环境( get_fun_env())。但是,为了使其正常工作,该函数必须是调用堆栈的一部分,位于调用 get_fun_env() 的位置,不幸的是,在上面的示例中并非如此。

    【讨论】:

      猜你喜欢
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多