Search code examples
rfunctiontidyverseexpression-evaluation

R evaluate character/string as the calling function name


I had a use case where I wanted to evaluate command line args as function names. For example,

r_script.R print --number 2

I will take r package docopt as an example here. The arguments typically are indexed by its own names, e.g. args$print refer to the string value "print". Actual R code would just be,

if (args$print){
   if (args$number){
       # call print()
       print(as.numeric(args$number))
   }
}

When I have a long list of functions like print, I'd write a massive if-else-loop to cope with it and it quickly becomes tedious.

Is there a way, for example using quosure, eval, or methods alike to replace this logic such that I can just write only a few lines of code to get the job done?

For example, the ideal logic would be,

func_enquo -> enquo(args$func)  # func is in place of `print`
func_enquo(value)  # what matters is the print argument here.

I have tried enquo by writing a wrapper function and it didn't work; I tried eval_tidy which was just to no avail (code is just not valid.)


Solution

  • If I understand it, you want to use a first argument as a function name? Then try to use get() somehow:

    do_something <- function(fct, arg) {
       get(fct)(arg)
    }
    
    do_something("print", "Hello")
    #>[1] "Hello"
    
    do_something("mean", 1:5)
    #> 3
    

    Note that you have to be careful what you pass into. Then you can refer to argument as args[1], not args$print, if it's always the first one somehow like this:

    func_enquo -> get(args[1])  # func is in place of `print`
    func_enquo(value)           # what matters is the print argument here.
    

    Does that help?