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
在它自己的环境中查找 y
和 z
,找不到它们,然后在环境中查找 f2
(称为 f3
),再次找不到它们,最后在环境中查找 f1
,找到它们,然后 return 6
。相反,f3
永远不会发现 y
和 z
和 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) })
创建,但最好考虑使用一些现有的对象系统而不是
而不是定义你自己的。
我无法理解 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
,找到它们,然后 return 6
。相反,f3
永远不会发现 y
和 z
和 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) })
创建,但最好考虑使用一些现有的对象系统而不是
而不是定义你自己的。