存在和流行:为什么这些功能不同?

pet*_*arp 8 scope r sapply

为什么两个功能fngn以下不同?我不认为他们应该,但我必须遗漏一些东西.

vars <- letters[1:10]
a <- b <- 1
fn <- function (d) {
    sapply( vars, exists )
}
gn <- function (d) {
    sapply( vars, function (x) { exists(x) } )
}
fn(d=2)
#    a     b     c     d     e     f     g     h     i     j 
# TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE 
gn(d=2)
#    a     b     c     d     e     f     g     h     i     j 
# TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE 
exists("i")
# [1] FALSE
Run Code Online (Sandbox Code Playgroud)

有两点不同:

  1. gn(d=2)d存在,但为什么不存在fn(d=2)
  2. fn(d=2)i存在,什么时候gn(d=2)不存在.这令人费解,因为我没有定义i任何地方.

注意:这是在R版本3.2.0上,似乎第二个行为是该版本的新功能(见下文).

MrF*_*ick 6

为什么i不同......

看起来R 3.2有变化.索引变量i添加到当前环境lapply(这是sapply实际调用).这与新行为一起强制评估传递给您正在应用的函数的参数.这意味着您现在可以访问循环中当前迭代的索引.

原因fngn行为不同的是,exists()在调用它的环境中查看.在这种情况下fn,即i创建此变量的环境.在这种情况下gn,它正在查看您的匿名函数的环境.当R在本地环境中找不到符号时,它会根据定义的函数位置搜索环境,而不是调用它们的位置.这意味着R将找不到i变量,因为您的匿名函数是在i变量不存在的位置定义的.

我们可以编写一个小帮助函数,以便更容易获取当前索引.

idx <- function() get("i", parent.frame(2))
sapply(letters[1:3], function(x) paste(idx(), x))
#     a     b     c 
# "1 a" "2 b" "3 c"
Run Code Online (Sandbox Code Playgroud)

据我所知,这是目前无证件的行为.它的未来版本可能会有所变化.

为什么d不同......

d变量的差异是一个更直接的范围问题.R再次创建了一个用于调用函数的新环境exists.此环境的父级是基础环境.因此,当您调用exists它时,它会查看它所在的位置(这是i存在的环境),并且因为它找不到d它,所以它会搜索作为基本环境的下一个父节点.从不搜索当前的功能环境.您可以使用显式搜索当前环境

fn <- function (d) {
    sapply( vars, exists, where=environment() )
}
fn(d=2)
#    a     b     c     d     e     f     g     h     i     j 
# TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE 
Run Code Online (Sandbox Code Playgroud)

有关RI中环境的更多信息,建议您阅读Advanced REnvironments部分