1

Can't find a question similar to what I am trying to do. I have a workhorse function that can take any of a class of custom-made sub-functions, with their respective arguments, and do certain processing on it, like the following toy examples:

func1 <- function(a, b, c) {a + b * c}

func2 <- function(x, y, z, bob, bleb) {(x / y)^bleb * z/bob}

workhorse <- function(m, n, o, FUN, ...) {
  result <- FUN(x, y, ...)
  [process result with m, n, and o]
}

By itself, this works perfectly well as intended, as in

foo <- workhorse(m, n, o, func1, a, b, c)
foo2 <- workhorse(m, n, o, func2, x, y, z, bob, bleb)

I am trying to create a wrapper for workhorse (meta_workhorse) that will accept a list of functions (by quoted name) to run through workhorse and combine the results, something like below.

FUN_list <- c('func1', 'func2')
ARGS_list <- list(c(a, b, c), c(x, y, z, bob, bleb))

meta_workhorse <- function(mm, nn, oo, FUN_list, ARGS_list) {
  meta_result <- sapply(1:length(FUN_list), function(x) {
    workhorse(mm, nn, oo, get(FUN_list[x]), ARGS_list[x], ...)
  }
}

The problem is that each of the sub-functions take different arguments, so I need to link the function name going into the get() function with the corresponding list of arguments in ARGS_list. I've tried everything I could think of, including do.calls, setting formals(workhorse), to no avail. How do I pass the arguments in this case?

EDIT: Nicola's answer solved most of the issue, but still have one subfuction (using a packaged function) keeps giving the error "unused argument ... = list(x, y)". Looking for some suggestions while I dig through previous ellipsis questions.

1 Answer 1

3

I guess you should declare your ARGS_list as a list of lists, instead of a normal list. Then, you can proceed to use do.call. An example (hoping that is what you are looking for):

   func1 <- function(a, b, c) {a + b * c}
   func2 <- function(x, y, z, bob, bleb) {(x / y)^bleb * z/bob}
   workhorse <- function(m, n, o, FUN, ...) {
     result <- FUN(...)
     result+m+n*o
   }
   FUN_list <- c('func1', 'func2')    
   ARGS_list <- list(list(a=1, b=2, c=3), list(x=4, y=5, z=6, bob=7, bleb=8))
   meta_workhorse <- function(mm, nn, oo, FUN_list, ARGS_list) {
      sapply(1:length(FUN_list), function(x) {
        do.call(workhorse,c(list(m=mm,n=nn,o=oo,FUN=get(FUN_list[x])),ARGS_list[[x]]))
      })
   }

   meta_workhorse(1,2,3,FUN_list,ARGS_list)
   # [1] 14.000000  7.143805
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you, that provided part of the solution. Still did not work on the real code, then I figured out that it had to be passed as ... = ARGS_list[[x]], since it was being passed through the sub functions as the ellipses. Works just fine now.
Spoke too soon. This works for most functions. I have one that repeatedly gives the following error: unused argument (... = list(n.trees = 20). This seems to imply that it cannot handle the arguments being passed as a list, in contrast to the other functions I'm working with. However, it still works if the arguments are passed directly (i.e. one function at a time). Is there a way to parse a list of arguments so that it looks like arguments being called directly? I'm stuck, again.
Provide as similar as possible prototypes of your sub-functions and try to isolate the error to make it reproducible. Then edit your question or (maybe better) ask another question.
traced the issue to the specific packaged function that I used in my wrapper function (gbm::gbm.fit). I ended up extracting the dot arguments with list(...), then recreating a do.call specifically for the gbm.fit function listing all of the standard arguments plus the dot arguments. However,even this did not work until I modified it to unlist(list(...)) first. I am at a loss why gbm.fit would behave this way, but the original answer seems to work fine for other packaged functions such as e1071:svm and glmnet::glm. In any case, I seem to be back on track for now. thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.