【问题标题】:What is the difference between assign() and <<- in R?R中的assign()和<<-有什么区别?
【发布时间】:2011-08-12 17:16:27
【问题描述】:

在 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。一种方法比另一种更好吗?为什么会这样?

【问题讨论】:

    标签: r functional-programming global-variables


    【解决方案1】:

    正如@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)
    }
    

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

    【讨论】:

      【解决方案2】:

      Thomas Lumley 回答了这个in a superb post on r-help the other day&lt;&lt;- 是关于封闭环境的,所以你可以这样做(我再次引用他在 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
      

      这是将&lt;&lt;- 用作具有词法范围的“超级赋值”的合法用途。而不是简单地在全球环境中分配。为此,Thomas 有这些选择词:

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

      非常好的建议。

      【讨论】:

      • 或许你应该link to it
      • 感谢 Dirk,我担心 &lt;&lt;- 有一个邪恶的应用程序,这个正确性和良好性的例子有助于澄清问题。为拉姆利先生加一
      【解决方案3】:

      根据手册页here

      运算符&lt;&lt;--&gt;&gt; 导致在环境中搜索被分配变量的现有定义。

      在实践中我从来没有这样做过,但在我看来,assign 在准确指定环境方面赢得了很多分数,甚至无需考虑 R 的范围规则。 &lt;&lt;- 在环境中执行搜索,因此有点难以解释。

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

      【讨论】:

      • 是的,但是您通常不知道要分配的环境的确切位置。对于大多数用途,&lt;&lt;- 是正确的选择。
      • @hadley 我似乎记得读过有人考虑从 R 中删除 &lt;&lt;- 作为运算符。
      • 如果你问我这不是一个机会,因为它会产生大量现有代码。 R 通常不会努力做到这一点。
      猜你喜欢
      • 2017-09-03
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      • 1970-01-01
      • 2016-01-10
      • 2021-02-23
      • 2010-11-19
      • 1970-01-01
      相关资源
      最近更新 更多