从函数调用时,有没有办法使 match.call + eval 组合起作用?

Is there a way to make match.call + eval combination work when called from a function?

我使用的包有 2 个函数,最终如下所示:

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,有什么办法可以避免这个错误?

有类似的问题,例如 or ,但我的特殊问题是我无法修改包含 eval 调用的代码部分。

是 pkgFun2 错了,所以我认为你运气不好,没有一些奇怪的扭曲。它需要将适当的环境传递给 eval();如果你不能修改它,那么你就不能修复它。

这个 hack 可能看起来有效,但在现实生活中却行不通:

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

编辑添加: 实际上,还有另一个不那么奇怪的 hack 应该适用于您原来的 pkgFun1pkgFun2。如果您强制 x 的计算发生在 myFun 中,以便 pkgFun1 永远不会看到表达式 x,它应该可以工作。例如,

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

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