如何能在不附加包一个非输入法通过调用其命名空间没有它的功能被发现的?如何能在不附加包一个非输入法通过

2019-05-31 23:19发布

的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()

我这样想着,直到最近...

行为

最近的这次SO问题突出,其中一个功能完善的隐藏在其包装的命名空间通过一个看似不相关的函数调用中仍然发现了一个情况:

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通过指出回答原来的问题,从该包GDATA,其包括功能gmodels进口reorder.factor其被分派到第二呼叫内部transform() T1不同于T2 ,因为第一通过下式计算stats:::reorder.default()和所述第二通过gdata:::reorder.factor()

我的问题

它是如何在上面调用的transform(data, group=reorder(...))用于调度机制reorder的发现,然后分发到gdata:::reorder.factor()

(安的回答应包括的范围规则,从涉及的统计信息基本包在GDATA一个看似很好的隐蔽方法函数的调用导致的解释。)


另外可能有帮助的细节

  1. 无论是gdata:::reorder.factor ,也不是GDATA包作为一个整体被明确gmodels进口。 下面是import*gmodels' 命名空间文件指令:

     importFrom(MASS, ginv) importFrom(gdata, frameApply) importFrom(gdata, nobs) 
  2. 存在用于任何方法reorder()transform()<environment: namespace:gmodels>也不在"imports:gmodels"

     ls(getNamespace("gmodels")) ls(parent.env(getNamespace("gmodels"))) 
  3. 卸下gmodels不会恢复reorder()的行为: gdata:::reorder.factor()仍然被分派:

     detach("package:gmodels") T3 <- transform(data, group=reorder(group,-num)) identical(T3, T2) # [1] TRUE 
  4. reorder.factor()没有被存储在在基础环境S3方法的列表:

     grep("reorder", ls(.__S3MethodsTable__.)) # integer(0) 

从过去几天的[R聊天线程包括一些额外的想法。 由于Andrie,布莱恩·迪格斯,和Gavin辛普森谁(与别人)应随意编辑或添加可能IMPT。 细节这个问题。

Answer 1:

我不知道如果我正确地理解你的问题,但主要的一点是, group是字符向量,而data$group是因素。

安装后gmodels ,呼吁reorder(factor)调用gdata:::reorder.factor 。 因此, reorder(factor(group))调用它。

transform时,函数的第一个参数的环境内进行评价,因此在T2 <- transform(data, group = reorder(group,-num)) group是因子。

更新

library重视的包导入装载命名空间。

> loadedNamespaces()
 [1] "RCurl"     "base"      "datasets"  "devtools"  "grDevices" "graphics"  "methods"  
 [8] "stats"     "tools"     "utils"    
> library(gmodels) # here, namespace:gdata is loaded
> loadedNamespaces()
 [1] "MASS"      "RCurl"     "base"      "datasets"  "devtools"  "gdata"     "gmodels"  
 [8] "grDevices" "graphics"  "gtools"    "methods"   "stats"     "tools"     "utils"    

为以防万一,在reorder一般存在于namespace:stats

> r <- ls(.__S3MethodsTable__., envir = asNamespace("stats"))
> r[grep("reorder", r)]
[1] "reorder"            "reorder.default"    "reorder.dendrogram"

而对于更多的细节

的电话reorder会搜索S3generics两个ENVS:

?UseMethod

首先在环境中的一般函数被调用,然后在用于其中的一般定义的环境(通常是命名空间)的登记数据的基础上。

然后, loadNamespace注册S3功能的命名空间。

所以,你的情况, library(gmodels) - > loadNamespace(gdata) - > registerS3Methods(gdata)

在此之后,你可以找到它:

> methods(reorder)
[1] reorder.default*    reorder.dendrogram* reorder.factor*    

   Non-visible functions are asterisked

然而,由于reorder.factor不附加您的搜索路径,你不能直接访问它:

> reorder.factor
Error: object 'reorder.factor' not found

也许这是整个场景。



文章来源: How can a non-imported method in a not-attached package be found by calls to functions not having it in their namespace?