# Re: [R] Puzzled over curve() syntax.

From: Duncan Murdoch <murdoch_at_stats.uwo.ca>
Date: Fri 28 Oct 2005 - 00:29:38 EST

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

R-help@stat.math.ethz.ch mailing list