<- 和 <<- 的区别

Difference between <- and <<-

案例 1:

rm(list = ls())
foo <- function(x = 6){
  set <- function(){
  x <- x*x}
  set()
x}
foo()
# [1] 6

案例 2:

rm(list = ls())
foo <- function(x = 6){
set <- function(){
  x <<- x*x}
  set()
  x}
foo()
# [1] 36

我读到 <<- 运算符可用于为与当前环境不同的环境中的对象赋值。它说可以对不在当前环境中的对象使用 <<- 进行对象初始化。我想问一下可以使用 <<- 初始化哪个环境的对象。我的环境是 foo 函数的环境, <<- 可以初始化函数外的对象还是当前环境中的对象?完全混淆什么时候使用 <- 什么时候使用 <<-

运算符<<-是父作用域赋值运算符。它用于将 最近的 父范围内的变量赋值到对其进行评估的范围。因此,这些赋值 "stick" 在函数调用之外的范围内。考虑以下代码:

fun1 <- function() {
    x <- 10
    print(x)
}

> x <- 5    # x is defined in the outer (global) scope
> fun1()
[1] 10      # x was assigned to 10 in fun1()
> x
[1] 5       # but the global value of x is unchanged

在函数fun1()中,一个局部变量x被赋值给值10,但在全局范围内该值x 没有改变。现在考虑重写函数以使用父作用域赋值运算符:

fun2 <- function() {
    x <<- 10
    print(x)
}

> x <- 5
> fun2()
[1] 10      # x was assigned to 10 in fun2()
> x
[1] 10      # the global value of x changed to 10

因为函数fun2()使用了<<-运算符,x"sticks"的赋值是在函数求完之后。 R 实际上做的是遍历 fun2() 之外的所有作用域,并寻找包含名为 x 的变量的 第一个 作用域。在这种情况下,fun2() 之外的唯一范围是全局范围,因此它在那里进行分配。

正如一些人已经评论的那样,<<- 运算符被许多人反对,因为它会破坏 R 脚本的封装。如果我们将 R 函数视为一个孤立的功能块,那么不应允许它干扰调用它的代码的状态。滥用 <<- 赋值运算符存在这样做的风险。

<<- 运算符可用于将变量分配给全局环境。使用 assign 函数比 <<- 更好。不过,您可能不需要使用 <<- - 函数所需的输出应作为 R 中的对象返回。

这是一个例子

f <- function(x) {
    y <<- x * 2 # y outside the function
}

f(5) # y = 10 

这相当于

f <- function(x) {
    x * 2
}

y <- f(5) # y = 10

有了赋值功能,

f <- function(x) {
    assign('y', x*2 envir=.GlobalEnv)
}

f(5) # y = 10