在 R 中,如何计算函数内特定环境中的表达式?
In R, how do I evaluate an expression in a specific environment within a function?
在我明显的天真中,我假设当一个人调用 eval
并指定一个环境 (envir
) 时,表达式 (expr
) 在该环境中被评估。
但是 :-)
这按预期工作:
xx <- 10
nn <- 20
exprs <- binom.test(x=xx,n=nn)
eval(exprs);
默认情况下,eval
在 parent.frame()
中求值,帮助显示 [t]函数求值的父框架是调用函数的环境.
所以在上面的例子中,这是全局环境,其中确实定义了 xx
和 nn
。到目前为止,还不错。
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);
这也符合预期; xxx
和 nnn
在 newEnv
环境中定义,binom.test
在该环境中计算。
现在我们将它包装在一个函数中(我正在尝试构建的那个 - 我正在使用 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);
}
}
}
当运行这个时,你得到:
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
所以,那个错误难倒了我。显然,x
和 n
存在于 tempEnvironment
中; tempEnvironment
传递给 eval
.
为什么这突然不起作用了?这在函数内部的工作方式不同吗?我是否漏掉了一些明显的东西?
我不确定为什么 expression()
在这种情况下不起作用。但是,如果您将 expr
写成字符串并将 expression(expr)
替换为 parse(text=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)
结果:
> 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
在我明显的天真中,我假设当一个人调用 eval
并指定一个环境 (envir
) 时,表达式 (expr
) 在该环境中被评估。
但是 :-)
这按预期工作:
xx <- 10
nn <- 20
exprs <- binom.test(x=xx,n=nn)
eval(exprs);
默认情况下,eval
在 parent.frame()
中求值,帮助显示 [t]函数求值的父框架是调用函数的环境.
所以在上面的例子中,这是全局环境,其中确实定义了 xx
和 nn
。到目前为止,还不错。
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);
这也符合预期; xxx
和 nnn
在 newEnv
环境中定义,binom.test
在该环境中计算。
现在我们将它包装在一个函数中(我正在尝试构建的那个 - 我正在使用 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);
}
}
}
当运行这个时,你得到:
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
所以,那个错误难倒了我。显然,x
和 n
存在于 tempEnvironment
中; tempEnvironment
传递给 eval
.
为什么这突然不起作用了?这在函数内部的工作方式不同吗?我是否漏掉了一些明显的东西?
我不确定为什么 expression()
在这种情况下不起作用。但是,如果您将 expr
写成字符串并将 expression(expr)
替换为 parse(text=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)
结果:
> 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