代码之家  ›  专栏  ›  技术社区  ›  Christopher DuBois

在R中编写函数,牢记作用域

  •  30
  • Christopher DuBois  · 技术社区  · 15 年前

    > a <- 3
    > b <- 3
    > x <- 1:5
    > fn1 <- function(x,a,b) a+b+x
    > fn2 <- function(x) a+b+x
    > fn1(x,a,b)
    [1]  7  8  9 10 11
    > fn2(x)
    [1]  7  8  9 10 11
    

    正如所料,这两个函数是相同的,因为 fn2 执行时可以“看到”a和b。但每当我开始利用这一点时,在大约30分钟内,我就在没有必要的变量(例如a或b)的情况下调用了该函数。如果我没有利用这一点,那么我觉得我在不必要地传递对象。

    4 回复  |  直到 15 年前
        1
  •  36
  •   ars    15 年前

    如果我知道我需要一个由一些值参数化并重复调用的函数,我会使用闭包来避免全局函数:

    make.fn2 <- function(a, b) {
        fn2 <- function(x) {
            return( x + a + b )
        }
        return( fn2 )
    }
    
    a <- 2; b <- 3
    fn2.1 <- make.fn2(a, b)
    fn2.1(3)    # 8
    fn2.1(4)    # 9
    
    a <- 4
    fn2.2 <- make.fn2(a, b)
    fn2.2(3)    # 10
    fn2.1(3)    # 8
    

    这巧妙地避免了引用全局变量,而是为a和b使用函数的封闭环境。当调用fn2实例时,修改全局变量a和b不会导致意外的副作用。

        2
  •  8
  •   Richie Cotton Joris Meys    15 年前

    有些语言不允许全局变量是有原因的:它们很容易导致代码中断。

    R中的作用域规则允许您以懒散的方式编写代码——让函数在其他环境中使用变量可以节省一些键入时间,并且对于在简单情况下进行操作非常有用。

    在上述示例中:

    最佳做法是使用fn1。

    或者,试试类似的方法

     fn3 <- function(x)
       {
          if(!exists("a", envir=.GlobalEnv))
          {
             warning("Variable 'a' does not exist in the global environment")
             a <- 1
          }
    
          if(!exists("b", envir=.GlobalEnv))
          {
             warning("Variable 'b' does not exist in the global environment")
             b <- 2
          }
    
          x + a + b
       }
    
        3
  •  3
  •   Tyler    15 年前

    当您只是在函数中使用全局变量时,还是在尝试分配变量时,会出现问题?如果是后者,我怀疑是因为你没有使用 <<- 作为函数中的赋值。使用时 <<- 似乎是黑暗面 1 它可能非常适合你的目的。如果是前者,则该函数可能掩盖了全局变量。

    以难以在本地屏蔽的方式命名全局变量可能会有所帮助。例如。: global.pimultiples <- 1:4*pi

        4
  •  0
  •   gappy    15 年前

    大多数语言都不鼓励使用全局变量,R也不例外。通常短函数使用短的通用变量名,可以在全局环境中填充。最安全的做法是a)在函数定义中包含所有变量b)