Puzzled over curve() syntax.
On 10/27/2005 9:50 AM, Rolf Turner wrote:
It's probably toadally elementary (and, like, duhhhhh) but
I can't figure out why the following doesn't work:
curve(function(x){qnorm(x,4,25)},from=0,to=1)
I get the error:
Error in xy.coords(x, y, xlabel, ylabel, log) :
'x' and 'y' lengths differ
But if I do
foo <- function(x){qnorm(x,4,25)}
curve(foo,from=0,to=1)
it goes like a train.
Also
plot(function(x){qnorm(x,4,25)},from=0,to=1)
works just fine.
I'm using
> version
_ platform sparc-sun-solaris2.9 arch sparc os solaris2.9 system sparc, solaris2.9 status major 2 minor 2.0 year 2005 month 10 day 06 svn rev 35749 language R This is just idle curiousity I guess, but I would like to deepen my understanding. There's probably something about the ``expression'' concept that I'm not grokking here ....
It's the way curve is written (and documented, though perhaps a little
obscurely). If you debug it, you'll see that eventually your function
gets assigned to a variable called "expr", and a nice list of values
gets assigned to "x", then it tries to evaluate
y <- eval(expr, envir = list(x = x), enclos = parent.frame())
But if you evaluate expr, you just get the function back, you don't call
it. The problem is that curve was written assuming you'd call it as
curve(qnorm(x,4,25),from=0,to=1)
in which case the expression "qnorm(x,4,25)" gets evaluated at those x
values and things are fine.
I don't think this is a bug, but it might be worth fixing so your code
works too. It's a little tricky, because to know that you passed a
function in, you probably want to evaluate it; but if you evaluate
"qnorm(x,4,25)" before you've set up x, you'll get an error.
A fix is to add an additional else clause after the first test, namely
else if (is.language(sexpr) && identical(sexpr[[1]],
as.name("function"))) {
expr <- substitute(do.call(expr, list(x)), list(expr=expr))
if (is.null(ylab))
ylab <- deparse(sexpr)
}
but this still doesn't handle the case where you've given a more general
expression that returns a function, e.g. picking one out of a list.
You'll probably need another argument to distinguish the case of an
expression returning y values from an expression returning a function,
and I'm not sure that level of elaboration would really be a good idea.
Duncan Murdoch