Re: [Rd] substitute and expression (Peter Dalgaard)

From: John Maindonald <john.maindonald_at_anu.edu.au>
Date: Thu, 19 Jul 2007 20:15:59 +1000

In this connection, note the following

 > a4 <- 4
 > plotThis <- bquote(alpha==.(a), list(a=a4))
 > do.call(plot, list(1:10, main=do.call(expression, c(plotThis))))
 > do.call(plot, list(1:10, main=do.call(expression, plotThis)))
Error in do.call(expression, plotThis) : second argument must be a list

 > ## Whereas plotThis has class "call", c(plotThis) has class "list"  > class(plotThis)
[1] "call"
 > class(c(plotThis))
[1] "list"

 > ## Thus, the following is possible:
 > do.call(plot, list(1:10, main=do.call(expression, list(plotThis))))

Marc Schwartz pointed out to me., some considerable time ago, that one could use bquote() and .() to create the elements of a list object whose elements can be plotted in parallel as required, e.g., for axis labels, thus:

 > plot(1:2, 1:2, xaxt="n")
 > arg1 <- bquote(""< .(x), list(x=1.5))
 > arg2 <- bquote("">= .(x), list(x=1.5))
 > axis(1, at=1:2, labels=do.call(expression, list(arg1, arg2)))

For a unified approach to use of do.call(expression, ...), maybe one should use bquote() and .()?

John Maindonald email: john.maindonald_at_anu.edu.au phone : +61 2 (6125)3473 fax : +61 2(6125)5549 Centre for Mathematics & Its Applications, Room 1194, John Dedman Mathematical Sciences Building (Building 27) Australian National University, Canberra ACT 0200.

On 18 Jul 2007, at 8:00 PM, r-devel-request_at_r-project.org wrote:

> From: Peter Dalgaard <P.Dalgaard_at_biostat.ku.dk>
> Date: 18 July 2007 1:39:50 AM
> To: Deepayan Sarkar <deepayan.sarkar_at_gmail.com>
> Cc: R Development Mailing List <r-devel_at_stat.math.ethz.ch>
> Subject: Re: [Rd] substitute and expression
>
>
> Deepayan Sarkar wrote:
>> On 7/16/07, Peter Dalgaard <p.dalgaard_at_biostat.ku.dk> wrote:
>>
>>> Deepayan Sarkar wrote:
>>>
>>>> Hi,
>>>>
>>>> I'm trying to understand whether the use of substitute() is
>>>> appropriate/documented for plotmath annotation. The following two
>>>> calls give the same results:
>>>>
>>>>
>>>>
>>>>> plot(1:10, main = expression(alpha == 1))
>>>>> do.call(plot, list(1:10, main = expression(alpha == 1)))
>>>>>
>>>>>
>>>> But not these two:
>>>>
>>>>
>>>>
>>>>> plot(1:10, main = substitute(alpha == a, list(a = 2)))
>>>>> do.call(plot, list(1:10, main = substitute(alpha == a, list(a =
>>>>> 2))))
>>>>>
>>>>>
>>>> Error in as.graphicsAnnot(main) : object "alpha" not found
>>>>
>>>> (as a consequence, xyplot(..., main = substitute(alpha)) doesn't
>>>> currently work.)
>>>>
>>>> On the other hand, this works:
>>>>
>>>>
>>>>
>>>>> foo <- function(x) plot(1, main = x)
>>>>> foo(substitute(alpha))
>>>>>
>>>>>
>>>> I'm not sure how to interpret ?plotmath; it says
>>>>
>>>> If the 'text' argument to one of the text-drawing functions
>>>> ('text', 'mtext', 'axis', 'legend') in R is an expression, the
>>>> argument is interpreted as a mathematical expression...
>>>>
>>>> and uses substitute() in its examples, but
>>>>
>>>>
>>>>
>>>>> is.expression(substitute(alpha == a, list(a = 1)))
>>>>>
>>>>>
>>>> [1] FALSE
>>>>
>>>>
>>> I think you need to take plotmath out of the equation and study the
>>> difference between objects of mode "call" and those of mode
>>> "expression". Consider this:
>>>
>>>> f <- function(...)match.call()
>>>> do.call(f, list(1:10, main = substitute(alpha == a, list(a = 2))))
>>> function(...)match.call()
>>> (1:10, main = alpha == 2)
>>>> do.call(list, list(1:10, main = substitute(alpha == a, list(a =
>>>> 2))))
>>> Error in do.call(list, list(1:10, main = substitute(alpha == a,
>>> list(a =
>>> 2)))) :
>>> object "alpha" not found
>>>
>>> The issue is that function ends up with an argument alpha == 2
>>> which it
>>> proceeds to evaluate (lazily), where a direct call sees
>>> substitute(.....). It is a general problem with the do.call
>>> mechanism
>>> that it effectively pre-evaluates the argument list, which can
>>> confuse
>>> functions that rely on accessing the original argument
>>> expression. Try,
>>> e.g., do.call(plot, list(airquality$Wind, airquality$Ozone)) and
>>> watch
>>> the axis labels.
>>>
>>
>> Right. Lazy evaluation was the piece I was missing.
>>
>>
>>> Does it work if you use something like
>>>
>>> main = substitute(quote(alpha == a), list(a = 2))?
>>>
>>
>> Not for xyplot, though I haven't figured out why. Turns out this also
>> doesn't work:
>>
>>
>>> plot(y ~ x, data = list(x = 1:10, y = 1:10), main = substitute
>>> (alpha))
>>>
>> Error in as.graphicsAnnot(main) : object "alpha" not found
>>
>> I'll take this to mean that the fact that substitute() works
>> sometimes
>> (for plotmath) is an undocumented side effect of the implementation
>> that should not be relied upon.
>>
> Probably the correct solution is to use expression objects. More or
> less
> the entire reason for their existence is this sort of surprises.
>
> plot(y ~ x, data = list(x = 1:10, y = 1:10), main =
> as.expression(substitute(alpha==a, list(a=2))))
>
> I'm not going to investigate why this is necessary in connection with
> plot(), but the core issue is probably
>
>> e <- quote(f(x)) ; e[[2]] <- quote(2+2)
>> e
> f(2 + 2)
>> f <- quote(f(2+2))
>> identical(e,f)
> [1] TRUE
>
> notice that since the two calls are identical, there is no way for
> e to
> detect that it was called with x replaced by an object of mode "call".
> Or put differently, objects of mode call tend to lose their
> "personality" in connection with computing on the language.
>
>
> --
> O__ ---- Peter Dalgaard ุster Farimagsgade 5, Entr.B
> c/ /'_ --- Dept. of Biostatistics PO Box 2099, 1014 Cph. K
> (*) \(*) -- University of Copenhagen Denmark Ph: (+45)
> 35327918
> ~~~~~~~~~~ - (p.dalgaard_at_biostat.ku.dk) FAX: (+45)
> 35327907



R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Thu 19 Jul 2007 - 10:42:27 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Thu 19 Jul 2007 - 14:36:49 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.