'How to have missing() parameter also be missing in recursive call when the parameter has a default value?

My R function uses missing() to switch between two alternative ways of specifying input data. However, if the input is a factor, I want to automatically apply the function on the factor levels instead, so I make a recursive call. Now I have the problem that I forward all arguments to the recursive call, so none of the parameters are missing anymore! How do I make a recursive call with all the parameters missing that are also missing in the parent call?

Minimal example:

f <- function(a, b = 1){
  print(missing(b))
  if(length(a)>0) f(a = a[-1], b = b)
}

f(1:2) prints:

[1] TRUE
[1] FALSE
[1] FALSE

What I want is


[1] TRUE
[1] TRUE
[1] TRUE

This works when b has no default value, so f is instead

f <- function(a, b){
...

Also of course I have the option to switch the recursive call using if(missing(b))

if(missing(b)) f(a = a[-1]) else f(a = a[-1], b = b)

... but this gets complicated for multiple parameters and also deprives me of the option to learn something about the strange wonders of parameter handling in R ;-)



Solution 1:[1]

You can capture the call with match.call, and substitute a for a[-1] in the call. Then instead of calling the function with arguments, use do.call, which will only supply the arguments initially put into the function in the recursive calls.

f <- function(a, b = 1){
  print(missing(b))
  
  call_list <- as.list(match.call())[-1]

  if(length(a) > 0) {
    a <- a[-1]
    call_list$a <- a
    do.call(f, call_list)
  }
}

f(1:2)
#> [1] TRUE
#> [1] TRUE
#> [1] TRUE

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Allan Cameron