Referring to package and function as arguments in another function

独自空忆成欢 提交于 2021-01-27 05:40:44

问题


I am trying to find methods for specific functions across different packages in R. For example methods(broom::tidy) will return all methods for the function tidy in the package broom. For my current issue it would be better if I could have the methods function in another function like so: f1 <- function(x,y){ methods(x::y) }

(I removed other parts of the code that are not relevant to my issue.) However when I run the function like this:

f1 <- function(x,y){ methods(x::y)}
f1(broom,tidy)

I get the error

Error in loadNamespace(name) : there is no package called ‘x’

If I try to modify it as to only change the function but keep the package the same I get a similar error :

f2 <- function(y){  methods(broom::y)}
f2(tidy)

Error: 'y' is not an exported object from 'namespace:broom'

How can I get the package and function name to evaluate properly in the function? Does this current issue have to do with when r is trying to evaluate/substitute values in the function?


回答1:


Both the :: and methods() functions use non-standard evaluation in order to work. This means you need to be a bit more clever with passing values to the functions in order to get it to work. Here's one method

f1 <- function(x,y){ 
  do.call("methods", list(substitute(x::y)))
}
f1(broom,tidy)

Here we use substitute() to expand and x and y values we pass in into the namespace lookup. That solves the :: part which you can see with

f2 <- function(x,y){ 
  substitute(x::y)
}
f2(broom,tidy)
# broom::tidy

We need the substitute because there could very well be a package x with function y. For this reason, variables are not expanded when using ::. Note that :: is just a wrapper to getExportedValue() should you otherwise need to extract values from namespaces using character values.

But there is one other catch: methods() doesn't evaluate it's parameters, it uses the raw expression to find the methods. This means we don't actually need the value of broom::tidy, we to pass that literal expression. Since we need to evaluate the substitute to get the expression we need, we need to build the call with do.call() in order to evaluate the substitute and pass that expression on to methods()



来源:https://stackoverflow.com/questions/58452820/referring-to-package-and-function-as-arguments-in-another-function

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!