我经常编写需要在我的环境中查看其他对象的函数.例如:
> 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
Run Code Online (Sandbox Code Playgroud)
正如所料,这两个函数都是相同的,因为它fn2
可以在执行时"看到"a和b.但每当我开始利用这一点时,在大约30分钟内我最终调用函数时没有必要的变量(例如a或b).如果我没有利用这一点,那么我觉得我不必要地绕过物体.
是否更好地明确函数需要什么?或者应该通过内联注释或函数的其他文档来处理?有没有更好的办法?
ars*_*ars 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
Run Code Online (Sandbox Code Playgroud)
这样可以很好地避免引用全局变量,而是使用函数的封闭环境来表示a和b.当调用fn2实例时,修改全局变量a和b不会导致意外的副作用.
有些语言不允许使用全局变量:它们很容易导致代码损坏.
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
}
Run Code Online (Sandbox Code Playgroud)