在下面的代码中,我希望f和最终的a都返回3.但事实上他们都返回2.为什么会这样?在评估承诺时,Hasn 3在封闭环境中取代了2?
a <- 1
f <- function(a){
a <<- 3
cat(a)
}
f(a <- 2)
a
请注意,如果我在调用f时使用=而不是&lt; - ,则最终a按预期为3,但f仍为2.
答案 0 :(得分:2)
让我们来看看代码
a <- 1
将值1分配给全局环境中的名称a
。
f <- function(a){...}
创建一个保存在全局环境中名称f
的函数。
f(a <- 2)
现在我们使用表达式f
作为参数调用函数a<-2
。不立即评估此表达式。它作为承诺传递。 a
的全球价值仍为1.
现在我们输入函数f
的主体。我们传入的表达式被赋值给函数作用域中的局部变量a
(仍未取消评估),而全局中的a
保留为1.事实上它们都涉及符号{{ 1}}无关紧要。这里的两个a
变量之间没有直接联系。
a
这会通过a <<- 3
将值3分配给父作用域中的a而不是<<-
作为本地作用域。这意味着此处引用的<-
不是现在持有传递给函数的参数的本地a
。因此,这会将全局范围中a
的值更改为3.最后
a
现在我们终于使用传递给函数的值,因为cat(a)
这里引用了本地函数范围中的a
。这会触发promise a
在调用范围(恰好是全局范围)中运行。因此,a <- 2
的全局值设置为2.此赋值表达式返回右侧值,因此a
显示“2”。
该功能退出并
cat()
显示全局环境中a
的值,现在为a
。在a
中的两个表达式之间的短暂时刻只有值3。
如果你在哪里打电话
f
这是非常不同的。现在我们不再将表达式传递给函数,我们将值2传递给命名函数参数f( a=2 )
。如果您尝试a
,则会收到错误,该函数无法识别名为“x”的参数。在这种情况下,没有花哨的懒惰表达/承诺评估,因为2是常量。这将在函数调用后将全局值设置为3。 <{1}}和f(x=2)
的行为方式相同。