Evaluate args of a function call and convert the call to a character vector in R

305 views Asked by At

I am trying to write a function which would take as argument a function call, evaluates numeric args of this function call and then return corresponding character vector. This is what I have came up with:

ConvertToCharacter <- function(function.call) {
  call.str <- deparse(substitute(function.call))
  return(call.str)
}

> a <- 1
> ConvertToCharacter(sum(2, a))
"sum(2, a)"

> ConvertToCharacter(ddply(mtcars, .(vs), summarize, col=mean(cyl)))
"ddply(mtcars, .(vs), summarize, col = mean(cyl))"

Now, I want the numeric args to be evaluated before getting converted into a character vector. So that ConvertToCharacter(sum(2, a)) would return "sum(2, 1)" instead. I tried passing env=parent.frame() to subsitute but it won't work. Any idea how I could go with this?

Thanks!

2

There are 2 answers

2
BrodieG On BEST ANSWER

You need to recursively inspect your call, evaluate the symbols, and sub in the values for the numeric ones like so:

ConvertToCharacter <- function(function.call, env=parent.frame()) {  
  call <- substitute(function.call)
  convert_recurse <- function(x, env) {
    if(is.call(x)) {
      return(as.call(lapply(x, match.fun(sys.call()[[1]]), env=env)))
    } else if (
      is.symbol(x) && 
      is.numeric(try(val <- eval(x, env), silent=TRUE))
    ) {
      return(val)
    } else {
      return(x)
    }    
  }
  deparse(convert_recurse(call, env))
}
a <- 1
ConvertToCharacter(sum(2, a))
lbsToKgs <- 2.2  
ConvertToCharacter(ddply(mtcars, .(vs), summarize, col=mean(cyl), wtkg=mean(wt * lbsToKgs)))

And this is what you get:

# [1] "sum(2, 1)"         
# [1] "ddply(mtcars, .(vs), summarize, col = mean(cyl), wtkg = mean(wt * "
# [2] "    2.2))"

Also, credit to Robert for the workaround the apply/Recall issue.

0
Davide Passaretti On
ConvertToCharacter <- function(function.call) {
library(stringr)
str_replace(deparse(substitute(function.call)),"a",eval(a,envir=.GlobalEnv))
}

I hope it helps