Why does curve not seem to work with elements extracted from a list?
Consider two seemingly identical functions, but built differently:
a <- function(value){
function(x) x value
}
m <- lapply(1:3, a)
f <- a(1)
all.equal(f, m[[1]])
#[1] TRUE
curve works for f, but not m[[1]]:
> curve(m[[1]])
Error in curve(m[[1]]) :
'expr' must be a function, or a call or an expression containing 'x'
But it works if the object is extracted before:
d <- m[[1]]
curve(d)
Is there a reason for it?
CodePudding user response:
curve() is a "magic" function that tries to interpret its input as an expression when possible; it doesn't always work.
@user2554330 comments that curve() is expecting (from ?curve):
The name of a function, or a call or an expression written as a function of
xwhich will evaluate to an object of the same length asx.
Instead, m[[1]] is an expression that evaluates to a function. In contrast, d is the name of a function. You can get what you want using curve(m[[1]](x)) which makes the input an expression written as a function of x.
In the code below, R looks at the expression passed to curve() and asks whether is.name(sexpr) is TRUE. This test passes for f but fails for m[[1]] (if you want to test it outside of the function context, you need to compare is.name(quote(f)) and is.name(quote(m[[1]])).
Weirdly enough, plot(m[[1]]) does work (it calls plot.function(), which calls curve() with different arguments internally).
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
}
