如何从另一个包中仅导入一个函数,而不加载整个名称空间 [英] How to import only one function from another package, without loading the entire namespace

查看:165
本文介绍了如何从另一个包中仅导入一个函数,而不加载整个名称空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我正在开发一个名为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 :

  1. 这很糟糕
  2. memisc覆盖基本的aggregate.formula函数,该函数破坏了几件事.例如,example(aggregate)会惨败.
  1. It is bad
  2. memisc overrides the base aggregate.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'

NAMESPACE

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

那么,您知道我如何从memisc导入description函数而不在我的环境中导入aggregate.formula吗?

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,请参见重新排序因数会导致不同的结果,具体取决于加载的软件包.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆