以下示例在什么情况下返回本地x与全局x?
xi'an博客在http://xianblog.wordpress.com/2010/09/13/simply-start-over-and-build-something-better/
上写了以下内容最大的问题之一是范围界定。考虑以下小宝石。
f =function() {
if (runif(1) > .5)
x = 10
x
}
此函数返回的x是随机的本地或全局的。还有其他示例,其中变量在函数体内的局部变量和非局部变量之间交替。没有明智的语言会允许这样做。它很难看,它使得优化变得非常困难。这不是唯一的问题,甚至因为范围界定和懒惰评估之间的相互作用而发生更奇怪的事情。
PS - 这个西安博客文章是由Ross Ihaka撰写的吗?
编辑 - 跟进问题。
这是补救措施吗?
f = function() {
x = NA
if (runif(1) > .5)
x = 10
x
}
答案 0 :(得分:6)
如果您编写的函数不接受参数,或者该函数依赖于当前帧之外的变量范围,则这只是一个问题。你要么i)在函数中传递你需要的对象作为该函数的参数,要么ii)在使用它们的函数内创建那些对象。
您的f
编码错误。如果你可能改变x
,那么你应该传递x
,可能设置默认值NA
或类似的,如果这是你想要随机翻转的另一面。< / p>
f <- function(x = NA) {
if (runif(1) > .5)
x <- 10
x
}
这里我们看到函数按照你的第二个函数工作,但是通过适当地将x
分配为具有适当默认值的参数。请注意,即使我们在全局工作空间中定义了另一个x
,这也有效:
> set.seed(3)
> replicate(10, f())
[1] NA 10 NA NA 10 10 NA NA 10 10
> x <- 4
> set.seed(3)
> replicate(10, f())
[1] NA 10 NA NA 10 10 NA NA 10 10
另一个好处是,如果您想要返回其他值而不是x
,则可以传入NA
。如果您不需要该工具,那么在中定义x <- NA
就足够了。
上述内容取决于您对f
实际要做什么,这在您的发布和评论中并不明确。如果您要做的只是随机返回10
或NA
,请定义x <- NA
。
当然,这个函数非常愚蠢,因为它无法利用R中的向量化 - 它是一个非常多的标量运算,我们知道它在R中很慢。更好的函数可能是
f <- function(n = 1, repl = 10) {
out <- rep(NA, n)
out[runif(n) > 0.5] <- repl
out
}
或
f <- function(x, repl = 10) {
n <- length(x)
out <- rep(NA, n)
out[runif(n) > 0.5] <- repl
out
}
罗斯的示例函数,我推测,故意简单而愚蠢地强调范围界定问题 - 它不应该被视为编写好的R代码的例子,也不应该是这样的。请相应地了解范围界定功能和代码,并且不会被咬。您甚至可能会发现可以利用此功能......
答案 1 :(得分:1)
如果'if'条件为真,'x'仅在函数中声明,所以如果'runif(1)&gt; .5'那么第二次提到x将使函数返回你的本地x( 10),否则它将返回一个全局定义的'x'(如果'x'没有全局定义那么它将失败)
> f =function() {
+ if (T)
+ x = 10
+ x
+ }
> f()
[1] 10
> f =function() {
+ if (F)
+ x = 10
+ x
+ }
> f()
Error in f() : Object 'x' not found
> x<-77
> f()
[1] 77