2

I am writing a function, where the inputs are arguments and name of another function. I would like to convert these arguments and function name into an unevaluated expression or call. For example, if this is the call to the function:

huh_fun(
  data = mtcars
  method = lm,
  formula = hp ~ mpg,
  method.args = list(weights = drat, subset = rep(TRUE, 32)) # list of additional arguments
)

I would like the function to return the following expression/call, unevaluated:

lm(hp ~ mpg, data = mtcars, weights = drat, subset = rep(TRUE, 32))

I've had success quoting the data=, method=, and formula= arguments and combining them into a call. But cannot figure out how to quote the method.args= argument, and add the list elements into function arguments. Any and all pointers are appreciated. Thank you~

Daniel D. Sjoberg
  • 8,820
  • 2
  • 12
  • 28

2 Answers2

1

Having fixed argument names in "huh_fun", we could construct an unevaluated call using "language" objects:

huh_fun = function(data, method, formula, method.args)
{
    ans = c(list(substitute(method), 
                 substitute(formula), 
                 data = substitute(data)), 
            as.list(substitute(method.args))[-1])
    as.call(ans)
}

huh_fun(
    data = mtcars,
    method = lm,
    formula = hp ~ mpg,
    method.args = list(weights = drat, subset = rep(TRUE, 32)))
#lm(hp ~ mpg, data = mtcars, weights = drat, subset = rep(TRUE, 
#    32))
alexis_laz
  • 12,884
  • 4
  • 27
  • 37
0

You could use deparse(substitute(x)) and paste it together. Generate the call with str2lang.

huh_fun <- function(data, method, formula, method.args) {
  str2lang(paste0(deparse(substitute(method)), "(", deparse(substitute(formula)), ", ",
         "data = ", deparse(substitute(data)), ", ", 
         gsub("list\\((.*)\\)$", "\\1", deparse(substitute(method.args))),
         ")"))
}

Result

huh_fun(
  data=mtcars,
  method=lm,
  formula=hp ~ mpg,
  method.args=list(weights=drat, subset=rep(TRUE, 32)) # list of additional arguments
)

# lm(hp ~ mpg, data = mtcars, weights = drat, subset = rep(TRUE, 32))
jay.sf
  • 60,139
  • 8
  • 53
  • 110