【问题标题】:Is it possible to make functions recognize variables in scopes above them?是否可以让函数识别它们上方范围内的变量?
【发布时间】:2012-07-31 00:44:53
【问题描述】:

我在 R 中工作,例如,我想做,

printx <- function() {
  x <- 1
  printy()
  return(x)
}

printy <- function() {
  print(x)
}

因为我不想继续传递大量变量(此外,全局环境中没有 x)。有没有办法做到这一点?所有函数都可以访问全局环境,但是函数环境和全局之间的呢?

【问题讨论】:

    标签: r


    【解决方案1】:

    也许

    printx <- function() {
      x <- 1
      printy()
      return(x)
    }
    
    printy <- function() {
      print(get('x',envir=parent.frame()))
    }
    
    > x<-0
    > printy()
    [1] 0
    > printx()
    [1] 1
    [1] 1
    

    这将使用printy 打印的x,该printy 与调用函数的环境相关联。

    另一种可能性是创建一个新环境

    e1<-new.env(parent = baseenv())
    
    > assign('x',12,envir=e1)
    > x
    [1] 0
    > get('x',e1)
    [1] 12
    

    【讨论】:

    • 打败我。做得好。但是请注意,它是not a great idea。传递参数列表会更好,而且不会带来太多麻烦。
    • @AriB.Friedman:传递环境是另一种选择,但您必须小心不要无意中修改环境中的变量,因为它们不是按值传递的。跨度>
    • 这也是一个不错的选择。与@Michael 的回答一起,产生了三种选择。为问题背后的问题万岁。
    • 谢谢,这正是我想要的。我假设如果我有一个接受同名变量的函数,分配它会覆盖父环境中的变量?
    • 您也可以将printy 的定义嵌套在printx 中,因为函数的环境继承自其定义环境。
    【解决方案2】:

    您可以使用闭包来获得类似的结果,而不会产生与上述风险相关的风险。在不确切知道您要做什么的情况下,很难提出一个相关的例子。但是下面的代码可能很有趣......

    create.functions <- function(x){
        list(
            function() x,
            function() x+1,
            function() x^2
        )
    
    }
    
    x <- 0
    
    f1 <- create.functions(5)
    f1[[1]]()
    [1] 5
    f1[[2]]()
    [1] 6
    f1[[3]]()
    [1] 25
    
    f2 <- create.functions(3)
    f2[[1]]()
    [1] 3
    f2[[2]]()
    [1] 4
    f2[[3]]()
    [1] 9
    
    x
    [1] 0
    

    请注意,您可以创建一组共享相同参数 x 的函数,而在全局环境中参数 x 和 x 的值之间不会发生任何冲突。如果您需要一组新的函数,其中 x 的参数定义不同,您可以创建一个新的集合。

    这甚至可以使依赖于函数套件的代码在更改参数值时无需编辑:

    f <- create.functions(5)
    f[[1]]()/f[[3]]()
    [1] 0.2
    
    f <- create.functions(3)
    f[[1]]()/f[[3]]()
    [1] 0.3333333
    

    请注意,同一行代码 f[[1]]()/f[[3]]() 会根据参数 x 的定义方式返回不同的结果。

    【讨论】:

      猜你喜欢
      • 2016-11-22
      • 2018-08-16
      • 2011-10-28
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      • 2012-06-06
      • 1970-01-01
      相关资源
      最近更新 更多