如何从另一个包中只导入一个函数,而不加载整个命名空间

时间:2013-11-07 14:24:46

标签: r namespaces

假设我正在开发一个名为foo的包,它希望使用description包中的memisc函数。我不想导入整个memisc命名空间,因为:

  1. 很糟糕
  2. memisc会覆盖基本aggregate.formula函数,这会破坏一些内容。例如,example(aggregate)会悲惨地失败。
  3. 该软件包包含以下文件:

    说明

    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开始:

    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
    

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

2 个答案:

答案 0 :(得分:25)

你不能。

如果在memisc字段中声明Imports:,则在加载包时将加载命名空间,并且包可以找到导出的对象。 (如果在Depends:中指定它,则命名空间将被加载并附加到搜索路径,这使得任何代码都可以找到导出的对象。)

加载命名空间的一部分是使用泛型注册方法。 (我看了但是找不到一个说明这一点的规范文档;我将呼吁将函数声明为NAMESPACE文件中的S3方法作为证据。)定义的方法与泛型保持一致泛型函数(或者,可能是泛型函数的命名空间)的可见性。

通常,包将为其创建的泛型或其定义的类定义方法。 S3对象系统没有正式定义S3类(或者创建类的包)的机制,但一般的想法是如果包定义了返回具有该类属性的对象的函数(并且是唯一的包),那个类就是那个包的类。如果这两个条件中的任何一个成立,就不会有问题。如果在包中定义了泛型,则只有在附加包时才能找到它;如果在包中定义了类,那么只有在附加和使用包时,该类的对象才会存在(因此会被调度)。

memisc示例中,两者都不成立。 aggregate通用在stats包中定义,formula对象也在stats包中定义(基于定义as.formula,{{ 1}}等等)因为它既不是[.formula的通用也不是memisc的对象,如果memisc只是简单的话,甚至可以看到效果(以及调派的方法)已加载但未附加。

有关此问题的另一个示例,但使用memisc,请参阅Reordering factor gives different results, depending on which packages are loaded

通常,将包方法不能控制对象或泛型的泛型方法添加到一起是不好的做法;如果它覆盖了核心包中的方法,那么加倍;如果它不是核心包中现有功能的向后兼容功能,那就非常了。

对于您的示例,您可能最好将reorder.factor的代码复制到您的包中,尽管该方法有其自身的问题和警告。

答案 1 :(得分:2)

有一点需要注意,我不太熟悉R环境和命名空间,也不知道这是否适用于包 - 我在编程中使用的解决方法是使用::来将该函数复制到我自己的函数中。

加载整个软件包可能会产生未知的后果,正如对OP的问题的评论中所讨论的那样,但它似乎没有将软件包的函数名称附加到R名称空间并掩盖现有的函数名称。

例:
my_memisc_description <- memisc::description