r-有没有一种方法可以让match.call+eval组合在从函数调用时工作



我使用的包有两个函数,最终看起来如下:

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)
}

编辑后添加:事实上,还有另一个不那么奇怪的破解方法应该适用于您的原始pkgFun1pkgFun2。如果强制在myFun中执行对x的求值,使pkgFun1永远看不到表达式x,那么它应该可以工作。例如,

myFun <- function(x) {
do.call("pkgFun1", list(group = x))
}

如果你这样做,那么在myFun(2)之后,pkgFun1变量call将是pkgFun1(group = 2),并且你不会得到关于x的错误。

最新更新