简体   繁体   English

如何通过调用在其名称空间中没有它的函数来找到未附加包中的非导入方法?

[英]How can a non-imported method in a not-attached package be found by calls to functions not having it in their namespace?

An R namespace acts as the immediate environment for all functions in its associated package. R命名空间充当其关联包中所有函数的直接环境。 In other words, when function bar() from package foo calls another function, the R evaluator first searches for the other function in <environment: namespace:foo> , then in "imports.foo" , <environment: namespace:base> , <environment: R_GlobalEnv> , and so on down the search list returned by typing search() . 换句话说,当来自包foo的函数bar()调用另一个函数时,R计算器首先在<environment: namespace:foo>搜索另一个函数,然后在"imports.foo"<environment: namespace:base><environment: R_GlobalEnv> ,依此类推,键入search()返回的搜索列表。

One nice aspect of namespaces is that they can make packages act like better citizens: unexported functions in <environment: namespace:foo> and functions in imports:foo are available only: (a) to functions in foo ; 命名空间的一个很好的方面是它们可以使包充当更好的公民: <environment: namespace:foo>未导出函数和imports:foo函数imports:foo仅可用:(a) foo中的函数; (b) to other packages that import from foo ; (b)从foo进口的其他包裹; or (c) via fully qualified function calls like foo:::bar() . 或者(c)通过完全限定的函数调用,如foo:::bar()

Or so I thought until recently... 或者直到最近才想到......

The behavior 行为

This recent SO question highlighted a case in which a function well-hidden in its package's namespace was nonetheless found by a call to a seemingly unrelated function: 这个最近的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

Its immediate cause 它的直接原因

@Andrie answered the original question by pointing out that gmodels imports from the the package gdata , which includes a function reorder.factor that gets dispatched to inside the second call to transform() . @Andrie回答了原始问题,指出gmodels从包gdata导入,其中包含一个函数reorder.factor ,它被调度到第二次调用transform() T1 differs from T2 because the first is calculated by stats:::reorder.default() and the second by gdata:::reorder.factor() . T1T2不同,因为第一个是由stats:::reorder.default()计算的,第二个是由gdata:::reorder.factor()

My question 我的问题

How is it that in the above call to transform(data, group=reorder(...)) , the dispatching mechanism for reorder finds and then dispatches to gdata:::reorder.factor() ? 如何在上面的transform(data, group=reorder(...))调用transform(data, group=reorder(...))reorder的调度机制找到然后调度到gdata:::reorder.factor()

(An answer should include an explanation of the scoping rules that lead from a call involving functions in the stats and base packages to a seemingly well-hidden method in gdata .) (答案应该包括对范围规则的解释,这些规则从涉及统计数据基础包中的函数的调用引导到gdata中看似隐藏得很好的方法。)


Further possibly helpful details 还可能有用的细节

  1. Neither gdata:::reorder.factor , nor the gdata package as a whole are explicitly imported by gmodels . gdata:::reorder.factorgdata包都不是由gmodels显式导入的。 Here are the import* directives in gmodels ' NAMESPACE file: 以下是gmodelsNAMESPACE文件中的import*指令:

     importFrom(MASS, ginv) importFrom(gdata, frameApply) importFrom(gdata, nobs) 
  2. There are no methods for reorder() or transform() in <environment: namespace:gmodels> , nor in "imports:gmodels" : <environment: namespace:gmodels>中没有reorder()transform()方法,也没有"imports:gmodels"

     ls(getNamespace("gmodels")) ls(parent.env(getNamespace("gmodels"))) 
  3. Detaching gmodels does not revert reorder() 's behavior: gdata:::reorder.factor() still gets dispatched: 分离gmodels不会恢复reorder()的行为: gdata:::reorder.factor()仍然会被调度:

     detach("package:gmodels") T3 <- transform(data, group=reorder(group,-num)) identical(T3, T2) # [1] TRUE 
  4. reorder.factor() is not stored in the list of S3 methods in the base environment: reorder.factor()未存储在基本环境中的S3方法列表中:

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

R chat threads from the last couple of days include some additional ideas. 过去几天的R聊天线程包括一些额外的想法。 Thanks to Andrie, Brian Diggs, and Gavin Simpson who (with others) should feel free to edit or add possibly impt. 感谢Andrie,Brian Diggs和Gavin Simpson(和其他人一起)应该随意编辑或添加可能的impt。 details to this question. 这个问题的细节。

I'm not sure if I correctly understand your question, but the main point is that group is character vector while data$group is factor. 我不确定我是否正确理解了你的问题,但重点是group是字符向量而data$group是因子。

After attaching gmodels , the call for reorder(factor) calls gdata:::reorder.factor . 附加gmodelsreorder(factor)调用reorder(factor)调用gdata:::reorder.factor so, reorder(factor(group)) calls it. 所以, reorder(factor(group))调用它。

In transform , the function is evaluated within the environment of the first argument, so in T2 <- transform(data, group = reorder(group,-num)) , group is factor. transform ,函数在第一个参数的环境中进行评估,因此在T2 <- transform(data, group = reorder(group,-num))group是factor。

UPDATED 更新

library attaches the import packages into loaded namespace. 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"    

Just in case, the reorder generic exists in namespace:stats : 以防万一, reorder泛型存在于namespace:stats

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

And for more details 并了解更多详情

The call of reorder will search the S3generics in two envs: reorder的调用将在两个环境中搜索S3generics:

see ?UseMethod ?UseMethod

first in the environment in which the generic function is called, and then in the registration data base for the environment in which the generic is defined (typically a namespace). 首先在调用泛型函数的环境中,然后在定义泛型的环境的注册数据库中(通常是命名空间)。

then, loadNamespace registers the S3 functions to the namespace. 然后, loadNamespace将S3函数注册到命名空间。

So , in your case, library(gmodels) -> loadNamespace(gdata) -> registerS3Methods(gdata) . 所以,在你的情况下, library(gmodels) - > loadNamespace(gdata) - > registerS3Methods(gdata)

After this, you can find it by: 在此之后,您可以通过以下方式找到它:

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

   Non-visible functions are asterisked

However, as the reorder.factor is not attached on your search path, you cannot access it directly: 但是,由于reorder.factor未附加到您的搜索路径中,因此您无法直接访问它:

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

Probably this is whole scenario. 可能这是整个场景。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否可以在包小插图中使用非导入的包? - Is it possible to use non-imported packages in a package vignette? 创建的 package 未从 NAMESPACE 文件中导入的包中运行函数 - Created package not running functions from imported packages in NAMESPACE file 有没有办法使用闪亮的下载按钮从应用程序下载(非导入/操纵)数据? - Is there a way to use shiny download buttons to download (non-imported/manipulated) data from the app? 如何自动将函数加载到 R 包的命名空间中 - How to automatically load functions into namespace of an R package 如何在包dev中打开的项目上自动加载和附加导入的函数? - How can I automatically load and attach imported functions on project open in package dev? 无法安装R软件包-找不到“ scales.so”,在NAMESPACE中声明但未找到S3方法 - Having trouble installing R package - “scales.so” not found, S3 methods declared in NAMESPACE but not found 未附加名称空间时的R包依赖性问题 - R package dependency issues when namespace is not attached 如何覆盖包命名空间中的不可见函数? - How do I override a non-visible function in the package namespace? 如何避免类名与“通过命名空间加载(而不是附加)”的包冲突(qdap&openssl) - How to avoid class name conflict with a package “loaded via a namespace (and not attached)” (qdap & openssl) 在R中使用quantmod包修复错误时遇到问题:继承错误(x,“xts”):找不到对象“M” - Having trouble fixing error using quantmod package in R : Error in inherits(x, “xts”): object 'M' not found calls
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM