我在理解 R 中的词汇范围时遇到问题。采用以下功能:
f1 <- function(x, y, z) x + f2()
f2 <- function() f3()
f3 <- function() y + z
如果我打电话给f1(1, 2, 3)
我希望f3
在它自己的环境中寻找y
和z
,而不是找到它们,然后在环境中寻找f2
(称为f3
(,再次找不到它们,然后最后在环境中寻找f1
,找到它们,然后返回6
。相反,f3
永远不会找到y
和z
并返回错误。
我收集到这是因为函数不会在调用它们的环境中查找,而是在最初定义它们的环境中查找,因此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向您展示了如何按照您的要求进行操作,并建议您重新考虑您的设计。 使这变得容易的一种可能的设计是将所有共享参数的函数放入一个大函数中。 例如
f1 <- function(x, y, z) {
f2 <- function() {
f3()
}
f3 <- function() {
y + z
}
x + f2()
}
另一种可能性是在公共环境中定义它们。 这很容易使用local({ f1 <- ..., f2 <- ..., f3 <- ..., list(f1, f2, f3) })
创建,但最好考虑使用一些现有的对象系统 而不是定义你自己的。