[R] Replacement in an expression - can't use parse()

Tony Plate tplate at acm.org
Tue Mar 27 18:45:02 CEST 2007

```Peter Dalgaard wrote:
> Daniel Berg wrote:
>> Dear all,
>>
>> Suppose I have a very long expression e. Lets assume, for simplicity, that it is
>>
>> e = expression(u1+u2+u3)
>>
>> Now I wish to replace u2 with x and u3 with 1. I.e. the 'new'
>> expression, after replacement, should be:
>>
>>
>>> e
>>>
>> expression(u1+x+1)
>>
>> My question is how to do the replacement?
>>
>> I have tried using:
>>
>>
>>> e = parse(text=gsub("u2","x",e))
>>> e = parse(text=gsub("u3",1,e))
>>>
>> Even though this works fine in this simple example, the use of parse
>> when e is very long will fail since parse has a maximum line length
>> and will cut my expressions. I need to keep mode(e)=expression since I
>> will use e further in symbolic derivation and division.
>>
>> Any suggestions are most welcome.
>>
> The short answer is substitute().
>
> However, this is not entirely trivial to apply if you have your
> expression already inside an expression() object.
>
> The easy thing to do is
>
>> substitute(u1+u2+u3, list(u2=quote(x),u3=1))
> u1 + x + 1
>
> but notice that this "autoquotes" the first argument, so
>
>> substitute(e, list(u2=quote(x),u3=1))
> e
>
> which is pretty much useless.
>
> (Arguably it would have been a better design to avoid this feature and
> require substitute(quote(.....)....) for the former case.)
>
> The way around this is to add a further layer of substitute() to insert
> the value of e:
>
> eval(substitute(substitute(call,list(u2=quote(x),u3=1)),list(call=e[[1]])))
> u1 + x + 1
>
> Notice that substitute will not go inside expression objects, so we need
> to extract the mode "call" object using e[[1]]. Also, the result is
> "call" not "expression". You may need an as.expression construct around
> the result to get exactly what you asked.
>

I usually use do.call() to do this kind of thing:

> e <- expression(u1+u2+u3)
> e
expression(u1 + u2 + u3)
> do.call("substitute", list(e[[1]], list(u2=quote(x),u3=1)))
u1 + x + 1
>

(and of course one can wrap the result in as.expression() to get an
expression back).

Are there any circumstances where this construct will produce different
results to the nested substitute suggested by Peter?

-- Tony

```