I would like to use substitute()
to do variable substitutions inside expressions, without evaluating the expressions. For example, I have:
expr1 <- expression(if(x){
return(y)
} else {
return(z)
})
What I would like to do is get the following result assigned to "expr1":
expression(if(cos(x)){
return(y)
} else {
return(z)
})
By doing something like this:
expr2 <- substitute(expr1, list(x=cos(x)))
But that doesn't work, since substitute doesn't evaluate it's first argument. And so I just get back the original variable:
expr1
Now here it says that to do substitutions in an expression assigned to a variable, I have to execute substitute()
twice, followed by eval()
, like this:
expr2 <- eval(substitute(substitute(e, list(x = cos(x))), list(e = expr1)))
When I execute this statement, I do get an expression assigned to "expr2", but it doesn't contain the required substitution:
expression(if (x) {
return(y)
} else {
return(z)
})
What syntax can I apply to "expr1" so that I get the result I would like assigned to "expr2", namely:
expression(if (cos(x)) {
return(y)
} else {
return(z)
})
This appears to do the trick
do.call('substitute', list(expr1[[1]], list(x=quote(cos(x)))))
# if (cos(x)) {
# return(y)
# } else {
# return(z)
# }
First I use do.call
to pass the unevaluated expression as a parameter to substitute()
rather than a double-substitute
. Secondly, expression()
is really like a container object. You're really interested in just changing the code block of the first element of your expression. You could have avoided the expression()
and just used quote()
to avoid the "unboxing"
expr2 <- quote(if(x){ return(y) } else { return(z) })
do.call('substitute', list(expr2, list(x=quote(cos(x)))))
Both of these will return a class of type "if". If you need to, you can wrap it in an as.expression()
.
as.expression(do.call('substitute', list(expr1[[1]], list(x=quote(cos(x))))))
# expression(if (cos(x)) {
# return(y)
# } else {
# return(z)
# })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With