代码之家  ›  专栏  ›  技术社区  ›  Eduardo Leoni

使用功能和环境

  •  3
  • Eduardo Leoni  · 技术社区  · 15 年前

    在最近的讨论之后(例如 1 , 2 )我现在正在我的一些代码中使用环境。我的问题是,如何创建根据参数修改环境的函数?例如:

    y <- new.env()
    with(y, x <- 1)
    f <- function(env,z) {
        with(env, x+z)
    }
    f(y,z=1)
    

    投掷

    Error in eval(expr, envir, enclos) : object 'z' not found
    

    我使用环境来同时将两组模拟分开(不重构我的代码,这是我为一组实验编写的)。

    3 回复  |  直到 14 年前
        1
  •  8
  •   Shane    15 年前

    最简单的解决方案是在引用对象时使用环境:

    y <- new.env()
    y$x <- 1
    f <- function(env,z) {
        env$x+z
    }
    f(y,z=1)
    

    你需要分配 z 对你的环境也有好处。

    y <- new.env()
    with(y, x <- 1)
    f <- function(env,z) {
        assign("z", z, envir=env)
        with(env, x+z)
    }
    f(y,z=1)
    

    另一个选择是 attach 这样变量就可以直接使用了。

    y <- new.env()
    with(y, x <- 1)
    f <- function(env,z) {
        attach(env)
        y <- x + z
        detach(env)
        y
    }
    f(y,z=1)
    

    后一种解决方案非常强大,因为它意味着您可以使用新环境中任何附加环境中的任何对象,但也意味着您需要非常小心全局分配的对象。

    编辑 :

    这很有趣,我不完全理解这种行为(即为什么 Z 不在 with 打电话)它最初与环境的创建有关,环境的创建导致它超出了函数的范围,因为此版本可以工作:

    f <- function(z) {
        y <- new.env()
        with(y, x <- 1)
        with(y, x+z)
    }
    f(y,z=1)
    
        2
  •  3
  •   hatmatrix    15 年前

    您只需要做一个更改就可以使示例正常工作-重新定义要使用的函数 substitute() f() :

    f <- function(env,z) {
        eval(substitute(x+z,list(z=z)), env)
    }
    

    这会很快变得模糊,特别是因为您甚至可以在 小精灵 (例如,替换 x+z 具有 y <- x+z ,并不是说这完全相关)但是开发者可以做出选择…

    另外,您可以替换 list(z=z) 在上面的替换表达式中 environment() (例如, substitute(x+z,environment()) )只要传递给的变量之间没有冲突的变量名 F-() 以及那些居住在你的“env”里的人,但你可能不想走得太远。

    编辑: 这里还有另外两种方法,第一种方法只是为了显示操作环境的灵活性,第二种方法更适合实际使用。

    1)修改“env”的封闭环境(但在退出函数前将其改回原始值):

    f <- function(env,z) {
      e <- environment(env)
      environment(env) <- environment()
      output <- with(env,x+z)
      environment(env) <- e
      output
    }
    

    2)函数当前环境中“z”的力计算(使用 环境() )而不是让它在表达式求值后保持为自由变量, X+Z 在'Env’中。

    f <- function(env,z) {
      with(environment(),with(env,x+z))
    }
    

    根据您所需的解析顺序,在符号值关联冲突的情况下-例如,如果在您的函数环境和创建的环境中都定义了“x”,则为“y”(您希望它假定“x”的哪个值?)-您可以将函数体定义为 with(env,with(environment(),x+z)) .

        3
  •  1
  •   Kenn    14 年前
     y <- new.env()
     with(y, x <- 1)
     f <- function(env,z) {
        with(env, x+z)
     }
     f(y,z=1)
    

    注意括号:)以下操作有效:

    with(env, x)+z