R函数从调用它的函数继承参数

R function inheriting arguments from function that called it

我无法理解 R 中的词法范围。采用以下函数:

f1 <- function(x, y, z) x + f2()
f2 <- function() f3()
f3 <- function() y + z

如果我调用 f1(1, 2, 3),我希望 f3 在它自己的环境中查找 yz,找不到它们,然后在环境中查找 f2(称为 f3),再次找不到它们,最后在环境中查找 f1,找到它们,然后 return 6。相反,f3 永远不会发现 yz 和 return 是错误。

我了解到这是因为函数不在调用它们的环境中查找,而是在最初定义它们的环境中查找,所以 f3 直接跳到全局环境,从不搜索其他功能的环境。是吗?

我想我可以通过在函数之间显式传递参数来使其工作,如下所示:

f4 <- function(x, y, z) x + f5(y, z)
f5 <- function(y, z) f6(y, z)
f6 <- function(y, z) y + z

但我宁愿不这样做,因为我的应用程序有很多共享参数的嵌套函数,并且在每次调用时都定义它们似乎很混乱且容易出错。

有没有更好的方法?

您当然可以定义函数,以便它们在调用环境中查找,而不必专门采用命名参数。然而,我想不出一个好的用例,尝试这样做表明您应该重新考虑您的设计。

无论如何,作为演示,您可以通过以下方式重写函数以获得您描述的行为:

f1 <- function(x, y, z) x + f2()
f2 <- function() f3()
f3 <- function() parent.frame(2)$y + parent.frame(2)$z

f1(1,2,3)
#> [1] 6

@AllanCameron 向您展示了如何按照您的要求进行操作,并建议您重新考虑您的设计。一种使这变得容易的可能设计是将所有共享 args 的函数放入一个大函数中。例如,

f1 <- function(x, y, z) {
   f2 <- function() {
     f3()
   }
   f3 <- function() {
     y + z
   }
   x + f2()
}

另一种可能性是在一个共同的环境中定义它们。这很容易使用 local({ f1 <- ..., f2 <- ..., f3 <- ..., list(f1, f2, f3) }) 创建,但最好考虑使用一些现有的对象系统而不是 而不是定义你自己的。