简体   繁体   English

在R中,如何评估函数中特定环境中的表达式?

[英]In R, how do I evaluate an expression in a specific environment within a function?

In my apparent naievety, I assumed that when one calls eval and specifies an environment ( envir ), the expression ( expr ) is evaluated in that environment. 在我显而易见的情况下,我假设当一个人调用eval并指定一个环境( envir )时,表达式( expr )将在该环境中进行评估。

However :-) 但是:-)

This works as expected: 这按预期工作:

xx <- 10
nn <- 20
exprs <- binom.test(x=xx,n=nn)
eval(exprs);

By default, eval evaluates in parent.frame() , which the help reveals is [t]he parent frame of a function evaluation is the environment in which the function was called. 默认情况下, evalparent.frame() eval值,帮助显示为[t]函数求值的父帧是调用函数的环境。

So in the above example, this is the global environment, where indeed, xx and nn are defined. 所以在上面的例子中,这是全局环境,确实定义了xxnn So far, so good. 到现在为止还挺好。

newEnv <- new.env();
assign('xxx', 10, envir = newEnv);
assign('nnn', 30, envir = newEnv);
exprs2 <- expression(binom.test(x=xxx,n=nnn));
eval(exprs2, envir=newEnv);

This also works as expected; 这也按预期工作; xxx and nnn are defined in the newEnv environment, and binom.test is evaluated in that environment. xxxnnn的在所定义newEnv环境, binom.test在该环境中进行评价。

Now we wrap this in a function (the one I'm trying to build - I'm building it using the pwr package, but for this example I'm using binom.test because it's base R and it still doesn't work :-) 现在我们将它包装在一个函数中(我正在尝试构建一个函数 - 我正在使用pwr包构建它)但是对于这个例子我使用的是binom.test因为它是基础R并且它仍然不起作用: - )

loopFunction <- function(expr,
                         ...) {

  ### Get all 'dots' in a named list
  arguments <- list(...);
  argNames <- names(arguments);

  if (any(length(tail(arguments, -2) > 1))) {
    stop("Only the first two arguments may have length > 1!");
  }

  for (esIndex in seq_along(arguments[[1]])) {
    for (pwrIndex in seq_along(arguments[[2]])) {
      tempEnvironment <-
        new.env();
      assign(argNames[1], arguments[[1]][esIndex],
             envir = tempEnvironment);
      assign(argNames[2], arguments[[2]][pwrIndex],
             envir = tempEnvironment);
      if (length(arguments) > 2) {
        for (i in 3:length(arguments)) {
          assign(argNames[i], arguments[[i]],
                 envir = tempEnvironment);
        }
      }
      print(argNames);
      print(as.list(tempEnvironment));
      print(ls(tempEnvironment));
      print(get('x', envir=tempEnvironment));
      print(get('n', envir=tempEnvironment));
      return(eval(expr = expression(expr),
                  envir = tempEnvironment)$estimate);
    }
  }
}

When running this, you get: 运行此时,您会得到:

loopFunction(binom.test(x=x,n=n), x=c(10,20), n=c(30, 100));

#> [1] "x" "n"
#> $x
#> [1] 10
#> 
#> $n
#> [1] 30
#> 
#> [1] "n" "x"
#> [1] 10
#> [1] 30
#> Error in binom.test(x = x, n = n): object 'x' not found

So, that error stumps me. 所以,那个错误让我很难过。 clearly, x and n exist in tempEnvironment ; 显然, xn存在于tempEnvironment ; and tempEnvironment is passed to eval . tempEnvironment传递给eval

Why does this suddenly no longer work? 为什么这突然不再起作用? Does this work differently inside functions? 这在功能内部有何不同? Am I missing something obvious? 我错过了一些明显的东西吗

I am not sure why expression() doesn't work in this context. 我不确定为什么expression()在这种情况下不起作用。 However, it works if you write expr as a string and replace expression(expr) by parse(text=expr) : 但是,如果您将expr编写为字符串并使用parse(text=expr)替换expression(expr) ,则它可以工作:

loopFunction <- function(expr,
                         ...) {

  ### Get all 'dots' in a named list
  arguments <- list(...);
  argNames <- names(arguments);

  if (any(length(tail(arguments, -2) > 1))) {
    stop("Only the first two arguments may have length > 1!");
  }

  for (esIndex in seq_along(arguments[[1]])) {
    for (pwrIndex in seq_along(arguments[[2]])) {
      tempEnvironment <-
        new.env();
      assign(argNames[1], arguments[[1]][esIndex],
             envir = tempEnvironment);
      assign(argNames[2], arguments[[2]][pwrIndex],
             envir = tempEnvironment);
      if (length(arguments) > 2) {
        for (i in 3:length(arguments)) {
          assign(argNames[i], arguments[[i]],
                 envir = tempEnvironment);
        }
      }
      print(argNames);
      print(as.list(tempEnvironment));
      print(ls(tempEnvironment));
      print(get('x', envir=tempEnvironment));
      print(get('n', envir=tempEnvironment));
      return(eval(expr=parse(text=expr), envir =tempEnvironment)$estimate)
    }
  }
}

loopFunction("binom.test(x, n)", x=10, n=30)

Result: 结果:

> loopFunction("binom.test(x, n)", x=10, n=30)
[1] "x" "n"
$`x`
[1] 10

$n
[1] 30

[1] "n" "x"
[1] 10
[1] 30
probability of success 
             0.3333333 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM