Re: [R] substitute in a named expression

From: Peter Dalgaard <p.dalgaard_at_biostat.ku.dk>
Date: Thu 23 Jun 2005 - 09:09:45 EST

Gabor Grothendieck <ggrothendieck@gmail.com> writes:

> On 6/22/05, Søren Højsgaard <Soren.Hojsgaard@agrsci.dk> wrote:
> > I have a 'named expression' like
> > expr <- expression(rep(1,d))
> > and would like to replace the argument d with say 5 without actually evaluating the expression. So I try substitute(expr, list(d=5)) in which case R simply returns expr which when I 'evaluate' it gives
> > eval(expr)
> > Error in rep.default(1, d) : invalid number of copies in rep()
> >
> > I've looked at ?substitute and ?expression (and other places) for ideas, but - well I guess there are some details which I haven't quite understood. Can anyone point me in the right direction?
>
> Try this:
>
> eval(substitute(substitute(qq, list(d=5)), list(qq = expr[[1]])))
>
> This aspect of R drove me crazy some time ago but Tony Plate finally figured
> it out and discussed it some time back:
> http://tolstoy.newcastle.edu.au/R/help/04/03/1247.html
> There is also a handy utility routine, esub, defined there.
>
> The key points are:
>
> - substitute won't go inside expressions but it will go inside call objects.
> In this case your expr is an expression but expr[[1]] is a call object with
> the desired contents. Note that quote will return a call
> object so you can avoid the [[1]] if you define expr as cl <- quote(rep(1,d))
> i.e.
> cl <- quote(rep(1,d))
> eval(substitute(substitute(cl, list(d=5)), list(cl = cl)))
>
> - substitute autoquotes anything inside it so one must substitute in
> the first argument to the inner substitute using a second outer substitute.
> That is, the outer substitute substitutes expr[[1]] (which is evaluated) into
> the first argument of the inner substitute.
>
> - the outer substitute wraps the result of the inner one in a call so we must
> perform an eval to get what is within the call. This part is explained in
> ?substitute
>
> Sorry if this is complicated but that seems to be how it works. Using
> the esub function defined in the link above you can simplify it substantially
> like this:
>
> esub(cl, list(d=5))
>
> # or
>
> esub(expr[[1]], list(d=5))

Yes, substitute() is a bass-ackward design and the automatic quoting of the first arg is a pain. It would have been much cleaner if standard semantics were used and you'd just quote() the argument when needed.

Your explanation of

> eval(substitute(substitute(qq, list(d=5)), list(qq = expr[[1]])))
 

is a tad long-winded though.

What happens is that the inner unevaluated

substitute(qq, list(d=5))

gets the qq replaced by the value of expr[[1]]. In casu it becomes

substitute(rep(1,d),list(d=5))

this then needs to be evaluated, yielding

rep(1,5)

-- 
   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@biostat.ku.dk)                  FAX: (+45) 35327907

______________________________________________
R-help@stat.math.ethz.ch mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html
Received on Thu Jun 23 09:14:45 2005

This archive was generated by hypermail 2.1.8 : Fri 03 Mar 2006 - 03:32:57 EST