我无法理解如何使用嵌套函数调用和参数计算。
这是一个简单的例子。我有一个带有一个数字参数的顶级函数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])))
<{1>}中的,但在我的实际应用中,topfunction
是由用户构建的,因此解决方案应该以{{1}}甚至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
,并评估myfun
在其他环境中,即lowerfunction
的环境中。
答案 0 :(得分:4)
这是一个相对简单的问题,但由于您正在进行非常非标准评估,因此您需要创建一个新的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)
的章节中描述了类似的技巧
答案 1 :(得分:2)
从myfun
中提升lowerfun
并修改eval
来电,如下所示。制作包时,如果您不导出myfun
,则无法直接从R_GlobalEnv
访问该包,但仍可以从lowerfun
内调用它。
topfunction <- function(x){
lowerfunction(myfun(first=x[1], second=x[2], third=if(length(x)>2) x[3]))
}
lowerfunction<-function(mycall){
mc <- match.call(definition = myfun, call = match.call()[[2]])
eval(mc, envir=parent.frame())
}
myfun <- function(first, second=0, third=NULL){
print(first)
print(second)
print(third)
}
示例运行:
> topfunction(1:3)
[1] 1
[1] 2
[1] 3
关闭主题: myfun
仍可通过致电R_GlobalEnv
从getFromNamespace("myfun", "mypackage")
访问
myfun
如果您真的希望将lowerfunction
保留在topfunction
内,为了保留概念点,您需要合并lowerfunction
和mc
的环境并评估{{ 1}}那里,但我不知道这是否可能(结果是,见@ hadley的回答)。
但是,您可以在评估之前从lowerfunction
的环境中复制x
的环境中未找到的变量(即 topfunction
)。由于延迟评估,这不会影响内存使用,除非它们被修改。
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]])
x <- get("x", parent.frame())
eval(mc)
}
然而,再次,由于您不知道用户将合并到topfunction
中的对象,您不能像上面那样硬编码,但必须通过从{{1提取所有名称来完成并通过mc
复制它们。这是有可能的,但我建议您省去麻烦并导出assign
和lowerfunction
。