在R中,assign()和〈〈-的区别是什么?

zlhcx6iw  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(704)

在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都被返回。一种方法比另一种方法更可取吗?为什么?

mdfafbf1

mdfafbf11#

托马斯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

<<-作为词法作用域的“超级赋值”是合理的用法,而不是简单地在全局环境中赋值。为此,托马斯有以下几个选择词:
邪恶和错误的用法是修改全局环境中的变量。
非常好的建议。

wfsdck30

wfsdck302#

根据手册第here页、
运算符<<-->>导致在环境中搜索被赋值变量的现有定义。
我在实践中从来没有这样做过,但在我看来,assign在精确指定环境方面赢得了很多分数,甚至不必考虑R的作用域规则。<<-在环境中执行搜索,因此有点难以解释。
编辑:为了尊重@Dirk和@Hadley,听起来assign是实际分配到全局环境的适当方式(当你知道你想要的时候),而<<-是“提升”到更广泛范围的适当方式。

gkn4icbw

gkn4icbw3#

正如@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)来指定封装环境。

相关问题