< - 和<< - 之间的差异

时间:2015-09-17 06:31:26

标签: r lexical-scope

案例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函数的环境,可以<<-初始化函数外部的对象或当前环境中的对象吗?完全混淆何时使用<-以及何时使用<<-

2 个答案:

答案 0 :(得分:8)

运算符<<-是父作用域赋值运算符。它用于将最近父作用域中的变量赋值给它所评估的作用域。因此,这些分配“粘在”函数调用之外的范围内。请考虑以下代码:

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“的赋值会”粘住“。 R实际上做的是遍历fun2()之外的所有范围,并查找包含名为x的变量的第一个范围。在这种情况下,fun2()之外的唯一范围是全局范围,因此它在那里进行分配。

正如一些人已经评论过的那样,<<-运算符被许多人所厌恶,因为它可以打破R脚本的封装。如果我们将R函数视为一个独立的功能,则不应该允许它干扰调用它的代码的状态。滥用<<-赋值运算符会冒这样做的风险。

答案 1 :(得分:2)

<<-运算符可用于将变量分配给全局环境。最好使用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

使用assign函数

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

f(5) # y = 10