R:范围,时间和<< -

时间:2018-02-06 20:54:21

标签: r scope promise arguments lazy-evaluation

在下面的代码中,我希望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.

1 个答案:

答案 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)的行为方式相同。