使用substitute在嵌套函数中的R语言应用

3

我有一个可能被嵌套(Inner)的函数和其他函数(一般来说这个函数是未知的),我称之为Outer,我希望Inner能够产生相同的结果,而不管包装函数(在下面的例子中是Outer)。

Inner <- function(x,baz,bang){
  # code stuff things ...
  x.prime = as.character(substitute(x))
  return(c(x.prime,y,z))
}

Outer <- function(y){
  Inner(y)
}
Inner(a)
# "a" "stuff" "things" , which is what I'm expecting, in particular the "a".
Outer(a)
# "y" .... , but I was expecting to get "a"?

当然,如果有更好的方法,我并不一定非要使用替代方法。
有人知道如何让Inner输出相同的结果,无论它是否被嵌套?
提前感谢。

1
你能提供一些关于你在这里尝试实现什么的细节吗? - josliber
这段代码对于简单的转换到另一种编程语言非常有帮助,本质上我想看看是否可以不强制用户使用双引号。 - csta
1个回答

7
以下是一个通用的大纲,应该能帮助您解决问题:
Inner <- function(x) {
  my.call <- quote(substitute(x))    # we quote this here because we are going to re-use this expression
  var.name <- eval(my.call)

  for(i in rev(head(sys.frames(), -1L))) { # First frame doesn't matter since we already substituted for first level, reverse since sys.frames is in order of evaluation, and we want to go in reverse order
    my.call[[2]] <- var.name         # this is where we re-use it, modified to replace the variable
    var.name <- eval(my.call, i)
  }
  return(var.name)
}
Outer <- function(y) Inner(y)
Outer2 <- function(z) Outer(z)

现在让我们运行这些函数:
Inner(1 + 1)
# 1 + 1
Outer(2 + 2)
# 2 + 2
Outer2(3 + 3)
# 3 + 3

Inner总是返回最外层的表达式(您永远看不到y或z,只能看到在.GlobalEnv中键入的表达式)。

这里的技巧是使用sys.frames(),并重复使用substitute,直到我们到达顶层。

请注意,这假定所有的“Outer”函数都只是将它们的参数转发到下一个内部函数。如果您有类似以下内容的内容,则可能会变得更加复杂/不可能:

Outer <- function(y) Inner(y + 1)

这段代码没有检查那种类型的问题,但在你的代码中可能应该进行检查。另外,要记住这里的假设是你的函数只会从R命令行调用。如果有人将他们的函数包装在你的函数周围,你可能会得到意想不到的结果。


感谢您提供的可行解决方案以及详尽的解释。 - csta
我不确定你上面的限制是否正确。我已经尝试过(使用你的Inner定义)Outer<-function(y) Inner(y+1); Outer2<-function(z) Outer(z+5),对于Outer2(r),我得到了r + 5 + 1(带有类型语言)。也许我误解了你的注释? - csta
@csta,这可能不是一个限制。我没有测试过,但担心它可能无法工作。根据您的测试结果看起来似乎不是问题。 - BrodieG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接