Gabor Grothendieck <[EMAIL PROTECTED]> writes: > On 6/22/05, Søren Højsgaard <[EMAIL PROTECTED]> 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 ~~~~~~~~~~ - ([EMAIL PROTECTED]) 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