R的本地/全球问题是什么?

时间:2011-07-14 06:43:43

标签: r programming-languages

以下示例在什么情况下返回本地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
}

2 个答案:

答案 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实际要做什么,这在您的发布和评论中并不明确。如果您要做的只是随机返回10NA,请定义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