Reputation: 9183
How do I do this in R
:
I have sourced a function with some name exampleFoo
suppose:
exampleFoo <- function(a, predefined, signature)
Given the character vector exampleFoo
, how can I use that to call the function with that name?
Upvotes: 0
Views: 82
Reputation: 174778
It depends if this is going on inside another function or at the top level. I'll take those in reverse order.
exampleFoo <- function(a, predefined, signature) {
1:10
}
FUN <- "exampleFoo"
get(FUN)
get(FUN)()
> get(FUN)
function(a, predefined, signature) {
1:10
}
> get(FUN)()
[1] 1 2 3 4 5 6 7 8 9 10
In a function, the match.fun
argument is most applicable here. get
looks for objects with the name supplied to it, whereas match.fun
only considers function objects when searching. This has the additional benefit then of not matching non-function objects that may have the same name.
FOO <- function(f) {
BAR <- match.fun(f)
BAR()
}
> FOO(FUN)
[1] 1 2 3 4 5 6 7 8 9 10
> FOO("exampleFoo")
[1] 1 2 3 4 5 6 7 8 9 10
You can't use match.fun
(easily?) at the top level as it is designed to perform matching in the parent frame of the caller and the Global environment doesn't have a parent (IIRC).
@agstudy suggests a switch
based approach to having a wrapper function that can call one of several pre-defined functions by name. In the comments there I proposed two simpler alternatives. Here I expand upon that:
foo1 <- function(method, ...) {
dots <- list(...)
FUN <- match.fun(method)
do.call(FUN, dots)
}
or
foo2 <- function(method = c("fun1", "fun2", "fun3"), ...) {
dots <- list(...)
method <- match.arg(method)
FUN <- match.fun(method)
do.call(FUN, dots)
}
I've written these as pretty general functions which take any arguments plus method
. If the functions reference by / passed to method
have a ...
argument, then these could be called directly, perhaps with one or more named arguments, e.g.
## assuming `method` refers to a function with a first argument `x` and also
## a `...` argument
foo3 <- function(method, x, ...) {
FUN <- match.fun(method)
FUN(x, ...)
}
Upvotes: 4
Reputation: 1925
text<-"exampleFoo"
exampleFoo<-function(x) print("Success")
eval(parse(text=paste(text,"()")))
#[1] "Success"
As @joran suggested, get()
seems to work as a replacement for eval(parse(text="..."))
get(text)()
#[1] "Success"
Upvotes: 1
Reputation: 121568
I would use switch
for this, something like :
algoFactory <- function (method = c("algo1", "alog2",
"algo3")
{
method = method[1]
switch(method, algo1 = {
res = algo1.Impl(...)
}, algo2 = {
res = algo2.Impl(...)
}, algo3 = {
res = algo3.Impl(...)
})}
And each time I add a new algorithm I update this main function. In your RscripT , you call it for example:
Rscript algoFactory.R 'algo1'
Upvotes: 1