I have a global function of roughly the form:
demo_fcn <- function(f, x1,x2){
r = x1 - x2
return(f(r))
}
I want to create this function in a general way so that users can add their own f
with their own custom inputs, so long as there is an input slot for r
. Say we take f
to be the following function
f <- function(input, factor){
out = input^factor
return(out)
}
In this case, input = r
, so that the user is able to call
demo_fcn(f(factor=2),x1=2,x2=3)
I get the error
Error in f(factor = 2) : argument "input" is missing, with no default
The desired outcome here should be the following code running
r = 2-3
f(input=r, factor=2)
The end goal is to implement this in a more complicated function, with multiple arguments for both demo_fcn
and f
demo_fcn <- function(f, x1,x2){
r1 = x1 - x2
r2 = x1 x2
return(f(r1,r2))
}
f <- function(input1, input2, factor1,factor2){
out = input^factor1 input2^factor2
return(out)
}
CodePudding user response:
One way is to pass a function (not a function call), and use ...
in the top function to pass additional arguments.
demo_fcn <- function(f, x1, x2, ...) {
r = x1 - x2
f(r, ...)
}
f <- function(input, factor){
out = input^factor
out
}
demo_fcn(f, x1=2, x2=5, factor=2)
# [1] 9
If you want to have multiple such functions, then you can do:
demo_fcn <- function(f1, f2, x1, x2, f1opts = NULL) {
r = x1 - x2
do.call(f, c(list(r), f1opts))
}
demo_fcn(f, x1=2, x2=5, f1opts=list(factor=2))
Yet another alternative, taking from curve
, which may match more closely what you're hoping for.
demo_fcn <- function(expr, x1, x2, xname = "x") {
r = x1 - x2
sexpr <- substitute(expr)
if (is.name(sexpr)) {
expr <- call(as.character(sexpr), as.name(xname))
} else {
if (!((is.call(sexpr) || is.expression(sexpr)) && xname %in%
all.vars(sexpr)))
stop(gettextf("'expr' must be a function, or a call or an expression containing '%s'",
xname), domain = NA)
expr <- sexpr
}
ll <- list(x = r)
names(ll) <- xname
eval(expr, envir = ll, enclos = parent.frame())
}
demo_fcn(f(x, factor=2), x1=2, x2=5)
# [1] 9
See ?curve
for more explanation of xname=
, but in short: use x
in your call to f(.)
though it does not use any object named x
in the local or other environment, it is just a placeholder. If you prefer, you can change to xname="input"
and demo_fcn(f(input,factor=2),...)
for the same effect, but realize that in that call, input
is still a placeholder, not a reference to an object.