Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Referring to package and function as arguments in another function

Tags:

function

r

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?

like image 900
Mike Avatar asked Oct 18 '19 14:10

Mike


People also ask

What do you call a function that is used as an argument of another 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.

Can you pass a function as an argument to another function in Python?

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.

Can a function argument be another function?

Functions, like any other object, can be passed as an argument to another function.

Is it right to pass an unknown function 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.


1 Answers

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()

like image 62
MrFlick Avatar answered Sep 27 '22 18:09

MrFlick