首页 > 解决方案 > 通过包+函数名引用 R 包中的函数

问题描述

我正在开发一种自动化工具,该工具在已知文件夹(例如/src)中接收正在开发的 R 包,并希望在更广泛的上下文中从包中运行某些功能:例如 running function do_a_thing()

一个问题是,尽管可以可靠地加载包,例如使用devtools::load_all("src"),但我不知道作者可能在文件Package字段中输入的包名DESCRIPTION

这意味着我不能只调用src::do_a_thing(),因为实际形式可能是 eg MyWeirdPackageName::do_a_thing()

我知道这个desc包支持查找这个包名:

library(desc)
desc <- description$new("src")
desc$get("Package")

# > Package: 'MyWeirdPackageName'

...并且还exists可以检查包中是否存在目标函数:

exists("do_a_thing", where=paste("package", desc$get("Package"), sep=":"), mode="function")

# > TRUE

...但是鉴于我知道(在运行时,作为字符向量)它的完全限定名称是,我怎么能真正调用MyWeirdPackageName::do_a_thing这个函数呢?

Vanillaget似乎无法通过接受where参数或将完全限定名称作为输入来处理命名空间方面:

testfn <- get(paste(desc$get("Package"), "::do_a_thing", sep=''), mode="function")

# > Error in get(paste(desc$get("Package"), "::do_a_thing", sep = ""), mode = "function"): object
#   'MyWeirdPackageName::do_a_thing' of mode 'function' was not found

鉴于我知道它存在以及它所在的包的名称,我如何从这个do_a_thing包中显式调用该函数?

标签: rdevtools

解决方案


我认为你可以使用eval(parse(text="code here"))技巧。例如,

mean(c(1,2,3,4))
#[1] 2.5

# is equivalent to

eval(parse(text="mean(c(1,2,3,4))"))
#[1] 2.5

所以在你的情况下,这会起作用。

eval(parse(text="MyWeirdPackageName::do_a_thing"))

如果您可以将包名称作为字符串获取(我认为您已经对此很熟悉了),那么您可以将其替换为:

packagename <- "???"
eval(parse(text=paste0(packagename, "::do_a_thing")))

推荐阅读