R 命名空间充当其关联包中所有函数的直接环境。换句话说,当函数bar()
从包装中foo调用另一个函数,R 求值器首先在中搜索另一个函数<environment: namespace:foo>
,然后在"imports.foo"
, <environment: namespace:base>
, <environment: R_GlobalEnv>
,依此类推,在输入返回的搜索列表中search()
.
命名空间的一个好处是它们可以使包表现得像更好的公民:未导出的函数<environment: namespace:foo>
和功能在imports:foo
仅适用于: (a) 中的函数foo; (b) 导入到其他包foo;或(c)通过完全限定的函数调用,例如foo:::bar()
.
或者直到最近我也是这么想的......
行为
最近的这个问题 https://stackoverflow.com/questions/10939516/data-frame-transformation-gives-different-results-when-same-code-is-run-before-a/10940237#10940237强调了一种情况,其中隐藏在其包的命名空间中的函数仍然通过调用看似不相关的函数找到:
group <- c("C","F","D","B","A","E")
num <- c(12,11,7,7,2,1)
data <- data.frame(group,num)
## Evaluated **before** attaching 'gmodels' package
T1 <- transform(data, group = reorder(group,-num))
## Evaluated **after** attaching 'gmodels
library(gmodels)
T2 <- transform(data, group = reorder(group,-num))
identical(T1, T2)
# [1] FALSE
其直接原因
@Andrie 回答了最初的问题,指出gmodels从包中导入gdata,其中包括一个函数reorder.factor
被分派到第二次调用内transform()
. T1
不同于T2
因为第一个是通过以下方式计算的stats:::reorder.default()
第二个由gdata:::reorder.factor()
.
我的问题
在上面的调用中是如何实现的transform(data, group=reorder(...))
,调度机制reorder
找到然后分派到gdata:::reorder.factor()
?
(答案应包括对范围规则的解释,这些规则是由涉及函数的调用引起的stats and base封装到一个看似隐藏得很好的方法gdata.)
更多可能有用的细节
-
Neither gdata:::reorder.factor
,也不gdata整个包是由显式导入的gmodels。这里有import*
中的指令gmodels' 命名空间 file:
importFrom(MASS, ginv)
importFrom(gdata, frameApply)
importFrom(gdata, nobs)
-
没有方法reorder()
or transform()
in <environment: namespace:gmodels>
,也不在"imports:gmodels"
:
ls(getNamespace("gmodels"))
ls(parent.env(getNamespace("gmodels")))
-
分离gmodels不恢复reorder()
的行为:gdata:::reorder.factor()
仍然被派遣:
detach("package:gmodels")
T3 <- transform(data, group=reorder(group,-num))
identical(T3, T2)
# [1] TRUE
-
reorder.factor()
不存储在基础环境中的S3方法列表中:
grep("reorder", ls(.__S3MethodsTable__.))
# integer(0)
过去几天的 R 聊天线程包含了一些额外的想法。感谢 Andrie、Brian Diggs 和 Gavin Simpson(以及其他人)可以随意编辑或添加可能的提示。这个问题的详细信息。