我在理解如何使用嵌套函数调用和参数求值时遇到麻烦。
这是一个简单的例子。我有一个带有一个数字参数的顶级函数topfunction
。在topfunction
内部,我调用了另一个函数lowerfunction
,该参数是对lowerfunction
内部定义的函数的调用。
topfunction<-function(x){
lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3]))
}
lowerfunction<-function(mycall){
myfun<-function(first,second=0,third=NULL){
print(first)
print(second)
print(third)
}
mc<-match.call(definition = myfun, call = match.call()[[2]])
eval(mc)
}
在
lowerfunction
内部,我使用match.call
捕获了函数调用,并尝试评估该调用。但是由于变量x
仅在topfunction
的环境中定义,因此评估失败:topfunction(x=1:3)
Error in print(first) : object 'x' not found
我知道我可以换线
lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3]))
作为
lowerfunction(substitute(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3])))
在
topfunction
中,但是在我的实际应用程序中,topfunction
由用户构造,因此解决方案应该以某种方式在lowerfunction
甚至在myfun
级别中发生。但是由于他们已经丢失了有关x
的信息,所以我不知道是否可以实现?在实际应用中,
topfunction
使用lowerfunction
构造模型并计算其可能性,而lowerfunction
的参数是一个可以包含函数调用的公式,该公式将通过eval
进行评估。这些函数仅在lowerfunction
中定义。另外,lowerfunction
也可以直接调用,即x<-1:3
lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3]))
# or
lowerfunction(myfun(first=x1,second=2)
因此,将
x
添加到lowerfunction
的参数列表的解决方案通常不适用。因此,问题在于
eval
应该从一个环境(包 namespace ,或者在这种情况下,从myfun
环境)获取lowerfunction
的定义,并在其他环境(即myfun
环境)中评估topfunction
的参数。 最佳答案
这是一个相对简单的问题,但是由于您进行的是非常不标准的评估,因此需要创建一个新的environment,并且所有这些操作都确保您可以从该环境访问所需的所有对象。
g <- function(x){
f1(f2(x[1], x[2], if(length(x) > 2) x[3]))
}
f1 <- function(mycall, parent = parent.frame()) {
# Parent contains x
# New environment that contains f2 and inherits from the parent
env <- new.env(parent = parent)
env$f2 <- function(first, second = 0,third = NULL) {
print(first)
print(second)
print(third)
}
# More idiomatic way of getting unevaluated expression
expr <- substitute(mycall)
eval(expr, env)
}
g(1:3)
我在有关domain specific languages的章节中描述了类似的技术