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

发布于 2024-11-03 11:08:38 字数 482 浏览 3 评论 0 原文

在 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。一种方法是否优于另一种方法,为什么?

The normal approach to writing functions in R (as I understand) is to avoid side-effects and return a value from a function.

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

In this case, the value computed from the input into the function is returned. But the variable x_squared is not available.

But if you need to violate this basic functional programming tenet (and I'm not sure how serious R is about this issue) and return an object from a function, you have two choices.

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

Both objects x_squared and x_times_x are returned. Is one method preferable to the other and why so?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

长发绾君心 2024-11-10 11:08:38

Thomas Lumley 在 关于 r-help the other 的精彩帖子中回答了这个问题日<<- 是关于封闭环境的,所以你可以做这样的事情(再次,我引用他 4 月 22 日的帖子 在此线程中):

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

这是 <<- 的合法使用作为“具有词法范围的超级赋值。而不是简单地在全局环境中分配。为此,托马斯有这样的选择:

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

非常好的建议。

Thomas Lumley answers this in a superb post on r-help the other day. <<- is about the enclosing environment so you can do thing like this (and again, I quote his post from April 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

This is a legitimate use of <<- as "super-assignment" with lexical scope. And not simply to assign in the global environment. For that, Thomas has these choice words:

The Evil and Wrong use is to modify
variables in the global environment.

Very good advice.

七度光 2024-11-10 11:08:38

根据手册页此处

运算符<<-->> 会在环境中搜索所分配变量的现有定义。

我在实践中从未需要这样做,但在我看来,assign 因准确指定环境而赢得了很多分,甚至无需考虑 R 的作用域规则。 <<- 在环境中执行搜索,因此解释起来有点困难。

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

According to the manual page here,

The operators <<- and ->> cause a search to made through the environment for an existing definition of the variable being assigned.

I've never had to do this in practice, but to my mind, assign wins a lot of points for specifying the environment exactly, without even having to think about R's scoping rules. The <<- performs a search through environments and is therefore a little bit harder to interpret.

EDIT: In deference to @Dirk and @Hadley, it sounds like assign is the appropriate way to actually assign to the global environment (when that's what you know you want), while <<- is the appropriate way to "bump up" to a broader scope.

时光暖心i 2024-11-10 11:08:38

正如@John 在他的回答中指出的,分配可以让您专门指定环境。一个具体的应用程序如下:

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

As pointed out by @John in his answer, assign lets you specify the environment specifically. A specific application would be in the following:

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)
}

where we use both <<- and assign. Notice that if you want to use <<- to assign to the environment of the top level function, you need to declare/initialise the variable. However, with assign you can use parent.frame(1) to specify the encapsulating environment.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文