I am sure it is just me not understanding how R works, but could somebody
explain why
curve(cos(x))
works and
curve(expression(cos(x))
does not?
I have done some investigating and here is what I found. If I comment out
the line of curve indicated below, both calls work fine.
function (expr, from, to, n = 101, add = FALSE, type = "l", ylab = NULL,
log = NULL, xlim = NULL, ...)
{
sexpr <- substitute(expr)
if (is.name(sexpr)) {
fcall <- paste(sexpr, "(x)")
expr <- parse(text = fcall)
if (is.null(ylab))
ylab <- fcall
}
else {
if (!(is.call(sexpr) && match("x", all.vars(sexpr), nomatch = 0)))
stop("'expr' must be a function or an expression containing
'x'")
# expr <- sexpr
if (is.null(ylab))
ylab <- deparse(sexpr)
}
lims <- if (is.null(xlim))
< ... >
This is confusing, since
substitiue(expression(cos(x)))
returns just
expression(cos(x)).
Must be some side effects I do not understand. What is even more confusing
is that the above code (with one line commented out) does not work when
called as
curve(parse(text="cos(x)"))
although
parse(text="cos(x)")
returns
expression(cos(x)).
What I am really trying to do is plot a rather compilcated expression that
has been built from pieces by pasting strings together. SInce the parse
function returns an expression I thought I could just feed the result of
parse to plot ( or curve).
Any help or explanation will be appreciated,
Andy
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._
plotting an expression
2 messages · apjaworski@mmm.com, Thomas Lumley
On Mon, 30 Apr 2001 apjaworski at mmm.com wrote:
I am sure it is just me not understanding how R works, but could somebody
explain why
curve(cos(x))
works and
curve(expression(cos(x))
does not?
The short answer is that cos(x) is an expression returning a real number (the cosine of the value of x) but expression(cos(x)) is an expression returning the expression cox(x), and so is not plottable. R> x<-0 R> evalq(cos(x)) [1] 1 R> evalq(expression(cos(x))) expression(cos(x))
I have done some investigating and here is what I found. If I comment out the line of curve indicated below, both calls work fine.
When I comment out that line I get
R> curve(cos(x))
Error in xy.coords(x, y, xlabel, ylabel, log) :
x and y lengths differ
function (expr, from, to, n = 101, add = FALSE, type = "l", ylab = NULL,
log = NULL, xlim = NULL, ...)
{
sexpr <- substitute(expr)
if (is.name(sexpr)) {
fcall <- paste(sexpr, "(x)")
expr <- parse(text = fcall)
if (is.null(ylab))
ylab <- fcall
}
else {
if (!(is.call(sexpr) && match("x", all.vars(sexpr), nomatch = 0)))
stop("'expr' must be a function or an expression containing
'x'")
# expr <- sexpr
if (is.null(ylab))
ylab <- deparse(sexpr)
}
lims <- if (is.null(xlim))
< ... >
This is confusing, since
substitiue(expression(cos(x)))
returns just
expression(cos(x)).
Must be some side effects I do not understand.
It's not side effects, it's evaluation. It's tricky. Suppose you type curve(cos(x)) Then expr contains a promise to compute the cosine of the value of x. Since x may not exist, this promise will cause an error when the evaluation is done (unless x happens to exist) As expr is a formal parameter of the function, substitute(expr) returns the unevaluated actual parameter, which is the expression cox(x). This expression, when evaluated in an environment containing a suitable vector x will return the vector of cosines of the values in x, which we can plot. OTOH if you type curve(expression(cos(x)) then expr contains a promise to evaluate expression(cos(x)), which returns the expression cos(x). When this is evaluated in a suitable environment you get the vector of cosines of x. But substitute(expr) will now return the unevaluated expression expression(cos(x)) and when you evaluate this you will get the expression cos(x) rather than a vector of cosines of the values of x. So the way the function is written it will work as documented, with your change it will fail when it should work, unless the correct x vector is coincidentally hanging around in the calling environment.
What is even more confusing
is that the above code (with one line commented out) does not work when
called as
curve(parse(text="cos(x)"))
although
parse(text="cos(x)")
returns
expression(cos(x)).
That's because curve() sneakily looks at the unevaluated parameter sexpr before evaluating it, and notices it isn't an expression depending on the symbol x (it's an expression depending on the string "cos(x)"). To prove this (it would be silly to do for any other reason) you can confuse your modified curve() into working with R> x<-"cos(x)" R> curve(parse(text=x))
What I am really trying to do is plot a rather compilcated expression that has been built from pieces by pasting strings together. SInce the parse function returns an expression I thought I could just feed the result of parse to plot ( or curve).
It's likely to be less painful to define a suitable vector x and use eval() to evaluate the expression. -thomas Thomas Lumley Asst. Professor, Biostatistics tlumley at u.washington.edu University of Washington, Seattle -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-help-request at stat.math.ethz.ch _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._