如何从另一个包中只导入一个函数,而不加载整个命名空间 [英] How to import only one function from another package, without loading the entire namespace
问题描述
假设我正在开发一个名为 foo
的包,它想使用 memisc
包中的 description
函数.我不想导入整个 memisc
命名空间,因为:
Suppose I'm developing a package, called foo
, which would like to use the description
function from the memisc
package. I don't want to import the whole memisc
namespace because :
- 不好
memisc
覆盖了基本的aggregate.formula
函数,这破坏了几件事.例如,example(aggregate)
会惨遭失败.
- It is bad
memisc
overrides the baseaggregate.formula
function, which breaks several things. For example,example(aggregate)
would fail miserably.
该软件包包括以下文件:
The package includes the following files :
描述
Package: foo
Version: 0.0
Title: Foo
Imports:
memisc
Collate:
'foo.R'
命名空间
export(bar)
importFrom(memisc,description)
R/foo.R
##' bar function
##'
##' @param x something
##' @return nothing
##' @importFrom memisc description
##' @export
`bar` <- function(x) {
description(x)
}
我认为使用 importFrom
不会加载整个 memisc
命名空间,而只会加载 namespace::description
,但这不是案子.从香草 R 开始:
I'd think that using importFrom
would not load the entire memisc
namespace, but only namespace::description
, but this is not the case. Starting with a vanilla R :
R> getS3method("aggregate","formula")
## ... function code ...
## <environment: namespace:stats>
R> library(foo)
R> getS3method("aggregate","formula")
## ... function code ...
## <environment: namespace:memisc>
R> example(aggregate)
## Fails
那么,您知道如何在我的环境中不获取 aggregate.formula
的情况下从 memisc
导入 description
函数吗?
So, do you know how I can import the description
function from memisc
without getting aggregate.formula
in my environment ?
推荐答案
你不能.
如果您在 Imports:
字段中声明 memisc
,则在加载包时将加载命名空间,并且您的包可以找到导出的对象.(如果你在 Depends:
中指定它,命名空间将被加载并附加到搜索路径,这使得任何代码都可以找到导出的对象.)
If you declare memisc
in the Imports:
field, the namespace will be loaded when the package is loaded and the exported objects will be findable by your package. (If you specify it in Depends:
, the namespace will be loaded and attached to the search path which makes the exported objects findable by any code.)
加载命名空间的一部分是向泛型注册方法.(我查看了但找不到说明这一点的规范文档;我将呼吁在 NAMESPACE
文件中将函数声明为 S3 方法的事实作为证据.)定义的方法与泛型并具有泛型函数的可见性(或者,可能是泛型函数的命名空间).
Part of loading a namespace is registering methods with the generic. (I looked but couldn't find a canonical documentation that says this; I will appeal to the fact that functions are declared as S3 methods in the NAMESPACE
file as evidence.) The defined methods are kept with the generic and have the visibility of the generic function (or, perhaps, the generic function's namespace).
通常,一个包会为它创建的泛型或它定义的类定义一个方法.S3 对象系统没有正式定义 S3 类(或创建该类的包)的机制,但一般的想法是,如果包定义了返回具有该类属性的对象的函数(并且是唯一的包确实),该类是该包的类.如果这两个条件中的任何一个成立,就不会有问题.如果包中定义了泛型,只有在附加包的情况下才能找到;如果类是在包中定义的,则该类的对象只有在附加和使用包时才会存在(并因此被分派).
Typically, a package will define a method either for a generic it creates or for a class it defines. The S3 object system does not have a mechanism for formally defining an S3 class (or what package created the class), but the general idea is that if the package defines functions which return an object with that class attribute (and is the only package that does), that class is that package's class. If either of these two conditions hold, there will not be a problem. If the generic is defined in the package, it can only be found if the package is attached; if the class is defined in the package, objects of that class would only exist (and therefore be dispatched on) if the package is attached and used.
在 memisc
示例中,两者都不成立.aggregate
泛型在 stats
包中定义,formula
对象也在 stats
包中定义(基于在定义 as.formula
、[.formula
等的包上)因为它既不是 memisc
的通用也不是 memisc
的对象,如果 memisc
被简单地加载但未附加,甚至可以看到效果(以及调度到的方法).
In the memisc
example, neither holds. The aggregate
generic is defined in the stats
package and the formula
object is also defined in the stats
package (based on that package defining as.formula
, [.formula
, etc.) Since it is neither memisc
's generic nor memisc
's object, the effects can be seen even (and the method dispatched to) if memisc
is simply loaded but not attached.
有关此问题的另一个示例,但使用 reorder.factor
,请参阅 Reordering factor 给出不同的结果,取决于加载了哪些包.
For another example of this problem, but with reorder.factor
, see Reordering factor gives different results, depending on which packages are loaded.
一般来说,将方法添加到包不控制对象或泛型的泛型中是不好的做法;如果它覆盖核心包中的方法,则更是如此;如果它不是核心包中现有功能的向后兼容功能,那就太糟糕了.
In general, it is not good practice to add methods to generics for which the package does not control either the object or the generic; doubly so if it overrides a method in a core package; and egregiously so if it is not a backwards compatible function to the existing function in the core packages.
对于您的示例,您最好将 memisc::describe
的代码复制到您的包中,尽管这种方法有其自身的问题和警告.
For your example, you may be better off copying the code for memisc::describe
into your package, although that approach has its own problems and caveats.
这篇关于如何从另一个包中只导入一个函数,而不加载整个命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!