[R] substitute in a named expression
Peter Dalgaard
p.dalgaard at biostat.ku.dk
Thu Jun 23 01:09:45 CEST 2005
Gabor Grothendieck <ggrothendieck at gmail.com> writes:
> On 6/22/05, Søren Højsgaard <Soren.Hojsgaard at 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 at biostat.ku.dk) FAX: (+45) 35327907
More information about the R-help
mailing list