我经常编写需要在我的环境中查看其他对象的函数。例如:
> 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)。如果我没有利用这一点,那么我觉得我不必要地绕过物体。
明确一个函数需要什么更好?或者应该通过内联注释或函数的其他文档来处理?还有更好的方法吗?
答案 0 :(得分:36)
如果我知道我需要一些参数化的函数并重复调用,我会通过使用闭包来避免全局变量:
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不会导致意外的副作用。
答案 1 :(得分:8)
有些语言不允许使用全局变量:它们很容易导致代码损坏。
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
}
答案 2 :(得分:3)
当您在函数中使用全局变量或尝试分配变量时,是否会出现问题?如果是后者,我怀疑是因为你没有在函数中使用<<-
作为赋值。虽然使用<<-
似乎是黑暗的一面1,但它可能非常适合您的目的。如果它是前者,则该函数可能掩盖了全局变量。
以一种难以在本地掩盖它们的方式命名全局变量可能会有所帮助。例如:global.pimultiples <- 1:4*pi
答案 3 :(得分:0)
在大多数语言中一般不鼓励使用全局变量,R也不例外。通常,短函数使用短名称和通用变量名称,这些名称可以填充在全局环境中。最安全的是a)包括函数定义中的所有变量b) not 以指定默认值。例如,写f =函数(a,b),而不是f =函数(a = 0,b = NA)。