2011-07-14 21 views
-2

下面的示例在什么情况下返回本地x与全局x?R的本地/全球问题是什么?

西安的博客中写道,在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 - 是由罗斯·哈卡写这篇西安博客文章?

编辑 - 跟进问题。

这是补救?

f = function() { 
    x = NA 
    if (runif(1) > .5) 
    x = 10 
    x 
} 
+2

该职位不是由罗斯写的,西安的噩转载部分/全部评论罗斯在第一链接到西安的噩张贴由发布行。你已经逐字复制了西安的Og逐字抄袭罗斯的评论。 –

+1

由于@GavinSimpson在他很好的答案指出,这是不是与R的问题,我曾经工作过的每个其他编程语言有某种机制,做同样的事情,即允许局部变量和全局变量。所以你应该能够在其他许多语言中复制这个小例子。 R是放松对强迫你声明变量的类型,但是这并不意味着你不应该... – Andrie

+0

这是某种形式的洁癖“重新啁啾”演习?我很困惑... – Chase

回答

1

的“x”仅在函数中声明,如果“如果”条件为真,所以如果“runif(1)> 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 
+0

哇,那太糟糕了! – Geoff

+0

所以你可以首先在函数中声明x = NA ...是否有一个普遍接受的过程? – Geoff

+4

@Jeff - 不,那还不错。如果你编写糟糕的R代码,这只会是坏事。如果您知道自己在做什么并希望利用该语言的功能,范围界定可能很有用。如果你不理解这些语言的特征,它也会咬你。 –

6

此,如果你写不功能仅仅是一个问题采用参数或功能依赖于当前帧之外变量的范围。你或者我)在函数中传递你需要的对象作为该函数的参数,或者ii)在使用它们的函数内部创建这些对象。

f不正确编码。如果您有可能改变x,那么你应该通过x中,可能设置的NA默认或类似的,如果这是你想要的随机翻转的对方是什么。

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的例子代码,也不会是这样的。请相应地了解范围功能和代码,并且不会被咬伤。你甚至可能会发现你可以利用这个功能...