我使用的包有两个函数,最终看起来如下:
pkgFun1 <- function(group) {
call <- match.call()
pkgFun2(call)
}
pkgFun2 <- function(call) {
eval(call$group)
}
如果我只调用pkgFun1(group = 2)
,它工作正常。但我想从一个函数调用它:
myFun <- function(x) {
pkgFun1(group = x)
}
myFun(x = 2)
## Error in eval(call$group) : object 'x' not found
如果我不能修改包函数,而只能修改myFun
,有什么方法可以避免这个错误吗?
也有类似的问题,比如match.call的问题,或者lapply或R中的用户定义函数中的非标准求值,但我的特殊问题是我不能修改包含eval
调用的代码部分。
是pkgFun2错了,所以如果没有一些奇怪的扭曲,我认为你运气不好。它需要将适当的环境传递给eval((;如果你不能修改它,那么你就不能修复它。
这种黑客攻击可能看起来有效,但在现实生活中却无效:
pkgFun1 <- function(group) {
call <- match.call()
f <- pkgFun2
environment(f) <- parent.frame()
f(call)
}
这样,您调用的是经过修改的pkgFun2
的副本,以便其环境适合评估调用。它在测试用例中有效,但在未来会给您带来难以言喻的悲伤,因为pkgFun2
中所有不本地的都将在错误的地方搜索。例如,
myFun <- function(x) {
eval <- function(...) print("Gotcha!")
pkgFun1(group = x)
}
myFun(x = 2)
# [1] "Gotcha!"
最好是修复pkgFun2
。这里有一个解决方案:
pkgFun1 <- function(group) {
call <- match.call()
pkgFun2(call, parent.frame())
}
pkgFun2 <- function(call, envir) {
eval(call$group, envir = envir)
}
编辑后添加:事实上,还有另一个不那么奇怪的破解方法应该适用于您的原始pkgFun1
和pkgFun2
。如果强制在myFun
中执行对x
的求值,使pkgFun1
永远看不到表达式x
,那么它应该可以工作。例如,
myFun <- function(x) {
do.call("pkgFun1", list(group = x))
}
如果你这样做,那么在myFun(2)
之后,pkgFun1
变量call
将是pkgFun1(group = 2)
,并且你不会得到关于x
的错误。