我一直在阅读 Hadley Wickham 的 Advanced R,以便更好地了解 R 的机制及其在幕后的工作原理。到目前为止,我很喜欢它,一切都很清楚。有一个问题占据了我的脑海,我还没有找到解释。
我非常熟悉 R 的作用域规则,它决定了如何将值分配给自由变量。但是,我一直在努力解决为什么 R 在第一种情况下无法通过词法范围找到形式论证的值的问题。考虑以下示例:
y <- 4
f1 <- function(x = 2, y) {
x*2 + y
}
f1(x = 3)
它通常会引发错误,因为我没有为参数 y
分配默认值.但是,如果我创建一个局部变量 y
在函数体中它不会抛出任何错误:我还在 Professeur Matloff 的书中读到参数就像局部变量一样,所以这就是为什么这个问题对我来说仍然是个谜。
f1 <- function(x = 2, y) {
y <- 4
x*2 + y
}
f1(x = 3)
而且这里也没有错误,原因很清楚:y <- 2
f2 <- function(x = 2) {
x*2 + y
}
f2()
非常感谢您提前。
最佳答案
请注意,R 只会在您使用该变量时抛出错误。如果你有
f1 <- function(x = 2, y) {
x*2 + 5
}
f1(x = 3)
# [1] 11
一切都会好的。那是因为该参数是一个“ promise ”,在您实际使用它之前不会解决。这使您可以执行以下操作f1 <- function(x = 2, y=x+5) {
x*2 + y
}
f1(x = 3)
# [1] 14
凡y
value 将实际使用 x
的值在评估 promise 时传递给函数。此外你还可以做f1 <- function(x = 2, y=z+2) {
z <- x + 10
x*2 + y
}
f1(x = 3)
[1] 21
哪里y
能够取z
的值当函数被调用时,它甚至不存在。再次这是因为参数值是 Promise 并且仅在实际使用时才进行评估。他们在评估时可以访问环境中的所有值。但请注意,这仅有效,因为默认参数值是在函数体的上下文中计算的。这与将值传递给函数时不同。在这种情况下,该值是在调用环境中计算的,而不是在本地函数体中计算的。所以你不能做f1(x = 3, y=z+2)
# Error in f1(x = 3, y = z + 2) : object 'z' not found
在第一个函数中出现错误的原因是 y
的值当您尝试在 x*2 + y
中使用它时不存在.因为你已经定义了 y
作为参数,它不再是“自由”变量,不会在父作用域中查找。您在第二个函数中不会出错,因为您重新绑定(bind)了 y
变量到局部函数变量,因此您根本不会使用参数值。如果你跑了
f1 <- function(x = 2, y) {
y <- 4
x*2 + y
}
f1(x = 3, y=200)
# [1] 10
2000基本消失了。重新分配 y
后,您将无法再访问该值. R 在重新定义之前不会检查变量是否已经存在,因此没有任何东西会尝试评估 promise 值 y
函数参数。一旦 promise 被评估,参数就会像局部变量一样。
关于r - 为什么 R 不能通过词法范围找到参数的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69124966/