[R] Puzzled over curve() syntax.

Duncan Murdoch murdoch at stats.uwo.ca
Thu Oct 27 16:29:38 CEST 2005


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




More information about the R-help mailing list