ndevln
ndevln

Reputation: 183

match.call() returns a function or a symbol, but symbols can't be used by do.call()

I want to do a recursive function call with modified arguments in R.

recursive_function_call <- function(call) {

    fun_call <- as.list(call) 
    fun <- fun_call[[1]]
    arguments <- fun_call[-1]

    ## Modify Arguments 
    arguments$drop_option <- NULL

    ## Call Function
    result <- do.call(what = fun, args = arguments)
    return(result)
}
recursive_function_call(match.call())

I want to call this function from an array of similar functions. If this gets called from a top-level function the variable fun will be of type symbol, while it gets on a lower level function call fun will be a function.

My problem is that do.call() fails when the function is a symbol, while for the arguments it's OK to be symbols.

My solution is to convert the symbol to a string.

if (is.symbol(fun_call[[1]])) fun <- as.character(fun_call[[1]]) else fun <- fun_call[[1]]
  1. Is there a better way to get the function of a call object?
  2. Is there a way to check the symbol will be available after I converted it into a string? Or can I avoid the conversion?

Upvotes: 6

Views: 380

Answers (1)

Konrad Rudolph
Konrad Rudolph

Reputation: 545528

As you’ve noticed, do.call constructs and invokes a call expression (and invokes it) from a function name (or function) and a list of arguments. But you already have a call expression, no need for do.call — so you can directly invoke it using eval or eval.parent:

recursive_function_call = function(call) {
    call$drop_options = NULL
    eval.parent(call)
}

recursive_function_call(match.call())

That said, I’m not sure what your function’s purpose is. Are you looking for Recall?

Alternatively, you can use as.call to coerce a list into a function call expression. And, once again, eval then evaluates it:

eval.parent(as.call(fun_cal))

— in fact, as.call is essentially the inverse of as.list on a call expression: identical(as.call(as.list(call)), call) is TRUE.

Upvotes: 5

Related Questions