Hi folks,
I'm working on some code that wraps around a variety of functions, which I don't necessarily know ahead of time. Some of the functions accept bare variable names (with no options for, e.g., strings or formulas) and do eval like this:
f <- function(x, y, data) {
mc <- match.call()
mx <- mc[[match("x", names(mc))]]
my <- mc[[match("y", names(mc))]]
x <- eval(mx, data, enclos = sys.frame(sys.parent()))
y <- eval(my, data, enclos = sys.frame(sys.parent()))
c(x, y)
}
df <- data.frame(a = 1:5, b = 5:1)
f(a, b, df)
#> [1] 1 2 3 4 5 5 4 3 2 1
But when I use a wrapper that passes arguments via ...
, it fails:
wrapper <- function(data, .f = f, ...) {
.f(data = data, ...)
}
wrapper(df, x = a, y = b)
#> Error in eval(mx, data, enclos = sys.frame(sys.parent())): object 'a' not found
Is there a general way to handle passing the arguments safely? A given function may or may not have that set up, and I can't change f()
in such a way to do this more generally.
For my own knowledge, I'd also like to know why it fails. ...
passes arguments without evaluating them, right? Despite the fact that it's failing in eval()
, I have a feeling that that's misleading. Is it something about then needing to take the argument from the matched call and inserting it into eval()
that evaluates it out of context? Or is it in fact something going on in eval()
?
Thanks!
Malcolm