Jou*_*ske 6 arguments r function lazy-evaluation
我无法理解如何使用嵌套函数调用和参数评估.
这是一个简单的例子.我有一个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)
}
Run Code Online (Sandbox Code Playgroud)
lowerfunction我在里面捕获函数调用match.call,并尝试评估调用.但由于变量x仅在环境中定义topfunction,评估失败:
topfunction(x=1:3)
Error in print(first) : object 'x' not found
Run Code Online (Sandbox Code Playgroud)
我知道我可以换线
lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3]))
Run Code Online (Sandbox Code Playgroud)
如
lowerfunction(substitute(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3])))
Run Code Online (Sandbox Code Playgroud)
in 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)
Run Code Online (Sandbox Code Playgroud)
因此,添加x到参数列表中的解决方案lowerfunction通常不适用.
所以问题是eval应该myfun从一个环境(包命名空间,或者在这种情况下从环境中lowerfunction)定义,并评估myfun其他环境中的参数,即在环境中topfunction.
这是一个相对简单的问题,但由于您正在进行非常非标准的评估,因此您需要创建一个新环境,并确保您需要的所有对象都可以从该环境访问。
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)
Run Code Online (Sandbox Code Playgroud)
我在我的领域特定语言一章中描述了类似的技术