有人可以解释R中`<<-`赋值运算符的行为吗?

时间:2019-04-17 16:43:14

标签: r

几个小时后,我在代码中发现一个错误,因为<<-关联运算符在r中的意外行为。我已经阅读了文档并浏览了Internet,但是我仍然不了解操作员的行为。

查看以下两个功能:

# Define a function a_counter
a_counter  <- function(){

  i <<- i + 1
  print(i)

}
> i <- 0
> a_counter()
[1] 1
> print(i)
[1] 1
> a_counter()
[1] 2
> print(i)
[1] 2
# Define a function not_a_counter
not_a_counter  <- function(){

  i <- 0
  i <<- i + 1
  print(i)

}
> i <- 0
> not_a_counter()
[1] 0
> print(i)
[1] 1
> not_a_counter()
[1] 0
> print(i)
[1] 1

第一段代码按预期运行,在两个环境(函数环境和全局环境)中的变量i在每个函数调用中都会增加。

第二段代码对我来说绝对是意外的。 i <<- i + 1不会将值分配给位于函数环境中的i,而是在全局环境中的i中进行了赋值。我希望两个环境都可以更新。

1 个答案:

答案 0 :(得分:4)

在您的a_counter中,只有一个值i。不是两个。当在函数中找到“自由变量”时,将在定义该函数的环境中对其进行查找。因此,当您在该函数中调用i时,它将转到全局环境以查找该值。然后,当您执行<<-时,函数环境中根本不会发生分配。 <<-总是开始在父级环境中查找。如果你看

counter_vars  <- function() {
  a <- 4 
  i <<- i + 1
  ls() 
}
counter_vars()
# [1] "a"

您将看到函数环境/闭包内部的唯一变量是a变量。 i变量在那里不存在。因此,使用原始功能,所有i都来自全局范围

a_counter  <- function(){    
  i <<- i + 1    # global i = global i + 1
  print(i)       # global i still (no local variable has been created)
}

因此,应该期望您在not_a_counter中看到的行为,因为<<-不会在当前环境中更改值。它总是开始寻找一个“向上”的环境。当你有

not_a_counter  <- function(){    
  i <- 0         # local i (always 0)
  i <<- i + 1    # global i == local i + 1 (always 0+1)
  print(i)       # local i (always still 0, local value not changed)
}

在函数中定义i变量后,该变量不再“空闲”。因此,i <- 0创建了一个局部变量,在i <<- i + 1部分中,右侧的i+1使用了该局部变量并将其分配给父环境中的i