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?
Higher Order Functions Because functions are objects we can pass them as arguments to other functions. Functions that can accept other functions as arguments are also called higher-order functions.
Summary. In Python you can pass function objects in to other functions. Functions can be passed around in Python. In fact there are functions built into Python that expect functions to be given as one or more of their arguments so that they can then call them later.
Functions, like any other object, can be passed as an argument to another function.
Using anonymous functions as arguments Note that functions are first-class citizens in JavaScript. Therefore, you can pass a function to another function as an argument.
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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With