Reputation: 8880
I am trying to write a custom curve
function where the ...
would be passed to the function rather than the plot: I would like to be able to use say:
curve2(dnorm, mean=2, sd=3)
I run into a problem with handling the ...
in a call
environment. Starting from a simplified prototype of curve
:
minicurve <- function (expr, from = 0, to = 1, ...)
{
sexpr <- substitute(expr)
expr <- call(as.character(sexpr), as.name("x"))
ll <- list(x = seq(from=from, to=to, length.out=100))
names(ll) <- "x"
y <- eval(expr, envir = ll, enclos = parent.frame())
plot(x = ll$x, y = y, type="l")
}
# This gives the same behaviour as `curve`:
minicurve(dnorm)
Now I would like to pass the ...
into the call
(instead of passing into plot
). Usually, this is very easy, one just need to pass the ...
into the function. However, the call
function behaves differently, and I am not sure how I should handle it. I can just use:
dot1 <- substitute(...)
expr <- call(as.character(sexpr), as.name(xname), dot1)
This will work, however it will pass only the first argument. I need hence to use someting like:
dots <- substitute(list(...))
expr <- call(as.character(sexpr), as.name(xname), dots)
But this doesn't work:
minicurve2 <- function (expr, from = 0, to = 1, ...)
{
sexpr <- substitute(expr)
dots <- substitute(list(...))
expr <- call(as.character(sexpr), as.name(xname), dots)
ll <- list(x = seq(from=from, to=to, length.out=100))
names(ll) <- "x"
y <- eval(expr, envir = ll, enclos = parent.frame())
plot(x = ll$x, y = y, type="l")
}
So how do I pass a list of ...
into the call
function? Thanks!
Upvotes: 5
Views: 523
Reputation: 206167
How about this
minicurve <- function (expr, from = 0, to = 1, ...) {
sexpr <- substitute(expr)
expr <- call(as.character(sexpr), as.name("x"))
ll <- list(x = seq(from=from, to=to, length.out=100))
names(ll) <- "x"
dots <- substitute(...())
expr <- as.call(c(as.list(expr), dots))
y <- eval(expr, envir = ll, enclos = parent.frame())
plot(x = ll$x, y = y, type="l")
}
Here we capture the ...
as a list via the substitute(...())
syntax. Then we convert the call to a list, append in the parameters, and turn it back into a call.
We test with
minicurve(dnorm, mean=2, sd=3)
minicurve(dnorm, mean=.5, sd=5)
Upvotes: 5