R中的assign()和<< - 有什么区别?

时间:2011-04-26 02:26:29

标签: r functional-programming global-variables

在R中编写函数的常规方法(据我所知)是避免副作用并从函数返回值。

contained <- function(x) {
  x_squared <- x^2
  return(x_squared)
}

在这种情况下,返回从函数输入计算的值。但变量x_squared不可用。

但是如果你需要违反这个基本的函数式编程原则(我不确定R对这个问题有多严重)并从函数中返回一个对象,你有两个选择。

escape <- function(x){
  x_squared  <<- x^2
  assign("x_times_x", x*x, envir = .GlobalEnv)
}

返回对象x_squaredx_times_x。一种方法比另一种更好吗?为什么会这样?

3 个答案:

答案 0 :(得分:18)

Thomas Lumley回答了这个问题in a superb post on r-help the other day<<-是关于封闭环境的,所以你可以做这样的事情(再次,我引用他的帖子从4月22日in this thread):

make.accumulator<-function(){
    a <- 0
    function(x) {
        a <<- a + x
        a
    }
}

> f<-make.accumulator()
> f(1)
[1] 1
> f(1)
[1] 2
> f(11)
[1] 13
> f(11)
[1] 24

这是<<-作为具有词法范围的“超级赋值”的合法用法。而不仅仅是在全球环境中分配。为此,托马斯有这些选择词:

  

邪恶和错误的用法是修改   全球环境中的变量。

非常好的建议。

答案 1 :(得分:2)

根据手册页here

  

运算符<<-->>导致搜索通过环境获取正在分配的变量的现有定义。

我从来没有在实践中这样做,但在我看来,assign在确定环境方面赢得了很多积分,甚至不必考虑R的范围规则。 <<-执行环境搜索,因此有点难以理解。

编辑:尊重@Dirk和@Hadley,听起来assign是实际分配给全球环境的合适方式(当你知道自己想要的时候),而<<-是“提升”到更广范围的适当方式。

答案 2 :(得分:0)

正如@John在他的回答中指出的那样,assign允许你专门指定环境。具体应用如下:

testfn <- function(x){

    x_squared <- NULL

    escape <- function(x){
        x_squared  <<- x^2
        assign("x_times_x", x*x, envir = parent.frame(n = 1))
    }

    escape(x)

    print(x_squared)
    print(x_times_x)
}

我们同时使用<<-assign。请注意,如果要使用<<-分配给顶级函数的环境,则需要声明/初始化变量。但是,使用assign,您可以使用parent.frame(1)来指定封装环境。