[Rd] c(<symbol>, <symbol) |-> expression instead of list

Gabor Grothendieck ggrothendieck at gmail.com
Thu Aug 27 14:34:09 CEST 2009


On Thu, Aug 27, 2009 at 8:19 AM, Martin
Maechler<maechler at stat.math.ethz.ch> wrote:
>>>>>> "GaGr" == Gabor Grothendieck <ggrothendieck at gmail.com>
>>>>>>     on Thu, 27 Aug 2009 07:32:42 -0400 writes:
>
>    GaGr> On Thu, Aug 27, 2009 at 6:18 AM, Martin
>    GaGr> Maechler<maechler at stat.math.ethz.ch> wrote:
>    >> Dear programmeRs,
>    >>
>    >> I'm proposing and looking into implementing a small change in
>    >> R's  c() handling of 'symbol's aka 'name's, and potentially also
>    >> 'language' parts.
>    >>
>    >> The main motivation is transparent programmatic construction of
>    >> expression()s;  and important use cases are expressions used for
>    >> "plot math", typically in
>    >>        axis(.., labels = *)
>    >> or    legend(.., legend = *)
>    >>
>    >> [BTW, Paul,  in  grid.legend(*, labels = *),  labels is *not*
>    >>  allowed to be an expression]
>    >>
>    >> Look at this code snippet {where the comments include the
>    >> results you see} :
>    >>
>    >> e <- expression(a, gamma, nu == 50, x^2 == 3.14, y <- 17, { x[i] <- sin(y^2 + exp(u[i])) })
>    >> length(e)
>    >> ## 6
>    >> ## Ok, what are the components like ?
>    >> ##
>    >> sapply(e, is.language)
>    >> ## [1] TRUE TRUE TRUE TRUE TRUE TRUE
>    >> ## aha, all are  "language",
>    >> ##
>    >> ## and specifically :
>    >> sapply(e, typeof)
>    >> ##[1] "symbol"   "symbol"   "language" "language"   "language" "language"
>    >> ## or in ``S - compatible'' language  {but S+ slightly differs here}:
>    >> sapply(e, mode)
>    >> ##[1] "name" "name" "call" "call" "call" "call"
>    >> sapply(e, class)
>    >> ##[1] "name" "name" "call" "call" "<-"   "{"
>    >>
>    >> Now, in "plotmath" situations,
>    >> you'd often want the '50' , '3.14' or '17'  be the content of
>    >> other R variables, and so we need  substitute()  or  bquote(),
>    >> and these directly result in "name" or "language" objects :
>    >>
>    >> However, you cannot very easily concatenate them to an
>    >> expression:
>    >>
>    >> z <- c(88, 143)
>    >> (e1 <- substitute(x[1]^2 == v, list(v = z[1])))
>    >> (e2 <- bquote(pi / r[i]^2 == .(z[2])))
>    >>
>    >> ## However,
>    >> c(e1, e2)  ## is a list, not an expression ...
>
>    GaGr> although as.expression(c(e1, e2)) is an expression.
>
>    GaGr> plot(0)
>    GaGr> legend("top", as.expression(c(e1, e2)))
>
>    GaGr> in light of which the savings is just one as.expression().
>
> That's correct.
> But my main point is that it's unnatural that
> an expression is "list-like" with components "language"
> and when I use  c() on these language-parts I don't get back the
> expression.
>
>
>    GaGr> Another possibility would be to add support for
>    GaGr> multiple arguments to bquote:
>
>    GaGr> plot(0)
>    GaGr> legend("top", bquote(x[1]^2 == .(z[1]), pi / r[i]^2 == .(z[2])))
>
> well, that would solve the use case I gave,
> but would actually result in making  bquote() return
> *either* a 'language'/'symbol'  *or*  an 'expression';
> which is called polymorphic behavior and often can be slightly
> confusing/complicating.

But that is already how quote() works, i.e. it can return objects
of different classes so that would not be unexpected.

>
>    GaGr> Then we would not need to use c() in the first place.
>
> (in that use case, yes)
>

Another possibility is to create equote() which would be like a multi-argument
bquote but consistently produces an expression.   That would be more
convenient than writing c(bquote(...), bquote(...))

Note that nothing here prevents the c() enhancement to be done as well.
The two approaches are independent.



More information about the R-devel mailing list