5

I am working in R trying to create a wrapper function that calls a specified internal function (which is some existing function) and does some things with it. My wrapper function will include an argument func for the internal function I want to call and this function will always have a particular standard structure with a particular argument of interest, but the argument might be called by a different name in different cases, so I also want an argument in my wrapper function arg.name that specifies the name of one of the arguments in the internal function. I also want to be able to specify additional arguments with the ellipses ... to allow other general inputs to the internal function. Here is an outline of what I want to do (but this code doesn't work):

#Example of the internal function
#This would be an existing function - not one that I program myself
#The variable n might be named something different in some cases
EXISTING.FUNCTION <- function(a, n) { a + n^2 }

#Example of the wrapper function
#It includes arg.name to specify the name of the variable
MY.WRAPPER.FUNCTION <- function(value, func, arg.name, ...) {
  
  #Evaluate the internal function using inputs wrapper inputs
  OUTPUT <- func(arg.name = value, ...)
  
  #Return the output
  OUTPUT }

I want to be able to call the wrapper function like this:

MY.WRAPPER.FUNCTION(value = 4, func = EXISTING.FUNCTION, arg.name = 'n', a = 3)

#What I want to get
[1] 19

#What I actually get
Error in func(arg.name = value, ...) : unused argument (arg.name = value)

I am not sure how to get R to recognise the character string arg.name as the name of the variable in the internal use of the specified internal function within the wrapper function. I think this uses one or more of the evaluation functions (e.g., substitute, quote, as.name, etc.) but I have not yet had any success in modifying the above code to have arg.name recognised as identifying the argument name in the internal function.


Additional information: The above is written to strip the problem back to essentials, but if it matters, the existing functions I want to work with are quantile functions for probability distributions. Usually these will have a probability argument called p but I want to allow for the possibility that someone programs a quantile function with a different name for the probability argument. I'm not sure if this context matters for the solution, but that is the motivation for the problem.

2
  • @SamR: Yes, there might be an input function like that, or it might do something different (but still dependent on m). I would like to avoid having to construct additional functions to bypass the problem. Commented Apr 29 at 10:30
  • 1
    Why not MY.WRAPPER.FUNCTION <- function(func, ...) do.call(func, list(...)) and just pass arg.name and value as an element of ...? Or, put another way, is this an XY problem? Commented Apr 29 at 11:05

2 Answers 2

6

You can use substitute() to create an unevaluated call to the supplied FUNC with ... expanded. Then add the VALUE as a named argument to the call using the ARG.NAME. Finally evaluate the constructed call in the caller’s environment.

EXISTING.FUNCTION <- function(a, n) a + n^2

MY.WRAPPER.FUNCTION <- function(VALUE, FUNC, ARG.NAME, ...) {
  call <- substitute(FUNC(...))
  call[[ARG.NAME]] <- substitute(VALUE)
  eval.parent(call)
}

MY.WRAPPER.FUNCTION(VALUE = 4, FUNC = EXISTING.FUNCTION, ARG.NAME = 'n', a = 3)
#> [1] 19

Compared to the do.call() approach, constructing the call like this has the benefit of not forcing the evaluation of ... and VALUE before the call to FUNC. This may or may not be important, depending on how FUNC treats its arguments.

(Note the slight obfuscation (capitalization) of the wrapper argument names. That’s for some protection against partial matching of named arguments in ... to the formals.)

Sign up to request clarification or add additional context in comments.

Comments

5

Your question contains a lot of design questions.

I am not too sure what you want. Quick-fix (dirty)

.my_function = \(a, n) a + n^2L # . to indicate internal use

wrapper = \(value, func, arg.name, ...) {
  args = list(...)
  args[[arg.name]] = value
  do.call(func, args)
}
> wrapper(value=4, func=.my_function, arg.name='n', a=3)
[1] 19

I do not see much sense behind this.

2 Comments

I've added some additional information in the question. The idea is that the internal function is an already existing function in R, not something I program myself.
As long as you don't care about the arguments in ... and value being evaluated before the call to func, this is definitely the more straightforward way to go.

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.