R名称空间访问和match.fun

时间:2012-08-16 15:27:48

标签: r namespaces package

我正在开发一个R包,其中一个函数包含对导入包名称空间的包中的函数的match.fun调用。但是在加载包时,match.fun调用找不到函数名。从Hadley Wickham's description我认为我做的一切都是正确的,但事实显然并非如此。

示例:

# in the package file header, for creation of the NAMESPACE via roxygen2:
##` @import topicmodels

# The function declaration in the package
ModelTopics <- function(doc.term.mat, num.topics, topic.method="LDA"){
  topic.fun <- match.fun(topic.method)
  output <- topic.fun(doc.term.mat, k=num.topics)
  return(output)

}    

然后在R:

> library(mypackage)
> sample.output <- ModelTopics(my.dtm, topic.method="LDA", num.topics=5)
Error in get(as.character(FUN), mode = "function", envir = envir) : 
  object 'LDA' of mode 'function' was not found

根据我对命名空间的理解,match.fun调用应该可以访问包名称空间,包括topicmodels函数。但这似乎并非如此。如果我将topicmodels直接导入R会话的全局命名空间,那么这是有效的。

非常感谢任何帮助。这是在OSX上运行的R64 2.14.1。

更新: 该套餐为here

重新描述文件,也许这就是问题:roxygen2不会使用Imports:语句更新DESCRIPTION文件。但是其他包都没有在那里列出;只有match.fun次来电才会受到影响。

重新提取NAMESPACE提取物,这是导入部分:

import(catspec)
import(foreach)
import(gdata)
import(Hmisc)
import(igraph)
import(lsa)
import(Matrix)
import(plyr)
import(RecordLinkage)
import(reshape)
import(RWeka)
import(stringr)
import(tm)
import(topicmodels)

2 个答案:

答案 0 :(得分:6)

我认为这是一个范围问题。虽然您已导入topicmodels,因此导入了LDA,但您尚未导出这些功能,因此它们在搜索路径中不可用。

来自?match.fun

  

match.fun不打算在顶层使用,因为它会   在调用者的父级中执行匹配。

因此,由于您在全局环境中使用ModelTopics,并且LDA在全局环境中不可用,因此match.fun调用失败。


在我看来,你有两个选择:

选项1:使用get

另一种方法是使用get来指定环境。考虑一下:尝试使用match.fun在包print.ggplot中查找ggplot2

match.fun("print.ggplot")
Error in get(as.character(FUN), mode = "function", envir = envir) : 
  object 'print.ggplot' of mode 'function' was not found

由于未导出print.ggplotmatch.fun无法找到它。

但是,get确实找到了它:

get("print.ggplot", envir=environment(ggplot))
function (x, newpage = is.null(vp), vp = NULL, ...) 
{
    set_last_plot(x)
    if (newpage) 
        grid.newpage()
    data <- ggplot_build(x)
    gtable <- ggplot_gtable(data)
    if (is.null(vp)) {
        grid.draw(gtable)
    }
    else {
        if (is.character(vp)) 
            seekViewport(vp)
        else pushViewport(vp)
        grid.draw(gtable)
        upViewport()
    }
    invisible(data)
}
<environment: namespace:ggplot2>

选项2:从您需要的topicmodels导出功能

如果您使用NAMESPACE中提供的topicmodels来完成必要的功能,那么您的代码也应该有效。

通过以下方式执行此操作:

  • 使用LDA
  • 选择性地将@export和其他函数导出到命名空间
  • 使用Depends: topicmodels声明依赖项 - 这与在全局环境中调用library(topicmodels)相同。这将有效,但可能是一种蛮力方法。这也意味着任何后续的library调用都会掩盖您的LDA函数,从而导致意外结果。

答案 1 :(得分:0)

回答我自己的问题:在重新整理更新的代码后,DESCRIPTION文件没有更新Imports:Depends:字段。因此match.fun问题。出于好奇,为什么这会影响match.fun而不影响其他地方对导入的包函数的一系列其他函数调用?