让我们抓住环境“namespace:stats”和“package:stats”
ns = getNamespace( "stats" )
pkg = as.environment( "package:stats" )
现在让我们在两个函数中获得“sd”函数:
nsSd = get( "sd" , envir = ns , inherits = FALSE )
pkgSd = get( "sd" , envir = pkg , inherits = FALSE )
它们是一样的吗?他们是!但“同样”是什么意思呢?参考或价值平等?
identical( nsSd , pkgSd )
这意味着引用相等,因为以下返回FALSE:
test1 = function() {}
test2 = function() {}
identical( test1 , test2 )
但如果这是真的,那就意味着Environment的框架可以包含函数指针和函数对象。使问题进一步复杂化的是,函数可以在一个环境中“生存”,但可以告诉函数其执行环境是另一个环境。钱伯斯SoDA似乎没有答案(它是一本密集的书,也许我错过了它!)
所以,我想要一个明确的答案。以下哪项是正确的?或者这里是否有错误的三分法?
nsSd
和pkgSd
是两个不同的对象(尽管每个都是副本
其他),pkgSd
中的对象执行ns
环境nsSd
和pkgSd
是指向同一对象的指针。 nsSd
是指向pkgSd
的指针,因此它们被视为相同的答案 0 :(得分:5)
它们是指向同一对象的指针。使用此answer to another question,我们可以检查两个对象是否引用内存中的相同位置。
are_same <- function(x, y)
{
f <- function(x) capture.output(.Internal(inspect(x)))
all(f(x) == f(y))
}
are_same(nsSd, pkgSd) #TRUE
are_same(1:5, 1:5) #FALSE
答案 1 :(得分:4)
这主要不是你主要问题的答案。但是,在这个问题上,我同意Dirk:只有一个sd()
函数,可以根据具体情况通过不同的范围路径访问它。例如,当您在命令行键入sd(x)
时,将通过sd
环境框架中的条目找到与名称package:stats
对应的函数。当您输入stats:::sd(x)
时,或当stats
包裹中的其他功能调用sd(x)
时,将通过namespace:stats
环境中的搜索找到该功能。
相反,我只是想说明使用test1()
和test2()
的示例并不真正暗示评估为identical
的对象的“引用相等” 。要查看这两者不是identical
的真正原因,请查看str()
显示的结构:
test1 <- function() {}
test2 <- function() {}
identical( test1 , test2 )
# [1] FALSE
str(test1)
# function ()
# - attr(*, "srcref")=Class 'srcref' atomic [1:8] 1 13 1 25 13 25 1 1
# .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x01613f54>
str(test2)
# function ()
# - attr(*, "srcref")=Class 'srcref' atomic [1:8] 1 13 1 25 13 25 1 1
# .. ..- attr(*, "srcfile")=Classes 'srcfilecopy', 'srcfile' <environment: 0x01615730>
如果您滚动到上面代码框的右侧,您将看到这两个函数的一个属性不同,即与其源文件关联的环境。 (我对这个属性知之甚少,但这里并不重要。重点是它们不是identical
!)
如果告诉R您不希望将sourcefile属性数据与所创建的每个函数保持一致,identical(test1, test2)
的“意外”行为就会消失:
options(keep.source=FALSE)
test1 <- function() {}
test2 <- function() {}
identical( test1 , test2 )
# [1] TRUE