r - 为什么 R 不能通过词法范围找到参数的值?

标签 r function arguments lexical-scope

我一直在阅读 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/

相关文章:

c++ - 我可以将参数传递给 SIGINT 吗?

java - 遍历所有 main() 参数

R数据转换

r - mutate_impl(.data,点): Column `x` is of unsupported type quoted call中的hchart错误

function - 将 varargin 解包为单个变量

javascript - Angularjs - 功能不起作用

r - 在 R 中使用非标准评估创建新列

r - 具有有序条形图并使用构面

php - 读取目录文件功能

c - 有没有办法获取在c中调用函数时使用的参数名称