我试图在R中的不同程序包中查找特定功能的方法。例如,methods(broom::tidy)
将返回程序包tidy
中功能broom
的所有方法。对于我当前的问题,最好将methods
函数放在另一个函数中,如下所示:
f1 <- function(x,y){
methods(x::y)
}
(我删除了与问题无关的其他代码部分。) 但是,当我运行这样的函数时:
f1 <- function(x,y){ methods(x::y)}
f1(broom,tidy)
我收到错误
loadNamespace(name)中的错误:没有名为“ x”的包
如果我尝试将其修改为仅更改功能但将软件包保持不变,则会收到类似错误:
f2 <- function(y){ methods(broom::y)}
f2(tidy)
错误:“ y”不是从“ namespace:broom”导出的对象
如何获取包和函数名称以在函数中正确评估?当前的问题是否与r
试图评估/替代函数中的值有关?
答案 0 :(得分:5)
::
和methods()
函数都使用非标准评估才能工作。这意味着您需要更加聪明地将值传递给函数,以使其正常工作。这是一种方法
f1 <- function(x,y){
do.call("methods", list(substitute(x::y)))
}
f1(broom,tidy)
在这里,我们使用substitute()
进行扩展,并将x
和y
的值传递到名称空间查找中。这样可以解决您可以看到的::
部分
f2 <- function(x,y){
substitute(x::y)
}
f2(broom,tidy)
# broom::tidy
我们需要替换项,因为很可能会有一个带有功能x
的软件包y
。因此,使用::
时不会扩展变量。请注意,如果您另外需要使用字符值从名称空间中提取值,则::
只是getExportedValue()
的包装。
但是还有另外一个陷阱:methods()
不评估其参数,它使用原始表达式来找到方法。这意味着我们实际上不需要broom::tidy
的值,我们可以传递该文字表达式。由于我们需要评估替代项以获得所需的表达式,因此我们需要使用do.call()
构建调用以评估substitute
并将该表达式传递给methods()