expression vs call
Asked Answered
W

3

7

What is the difference between an expression and a call?

For instance:

func <- expression(2*x*y + x^2)
funcDx <- D(func, 'x')

Then:

> class(func)
[1] "expression"
> class(funcDx)
[1] "call"

Calling eval with envir list works on both of them. But Im curious what is the difference between the two class, and under what circumstances should I use expression or call.

Woeful answered 3/12, 2013 at 15:47 Comment(1)
Did you already read ?expression and ?call? It's a good place to start.Meridithmeriel
T
9

You should use expression when you want its capacity to hold more than one expression or call. It really returns an "expression list". The usual situation for the casual user of R is in forming arguments to ploting functions where the task is forming symbolic expressions for labels. R expression-lists are lists with potentially many items, while calls never are such. It's interesting that @hadley's Advanced R Programming suggests "you'll never need to use [the expression function]": http://adv-r.had.co.nz/Expressions.html. Parenthetically, the bquote function is highly useful, but has the limitation that it does not act on more than one expression at a time. I recently hacked a response to such a problem about parsing expressions and got the check, but I thought @mnel's answer was better: R selectively style plot axis labels

The strategy of passing an expression to the evaluator with eval( expr, envir= < a named environment or list>) is essentially another route to what function is doing. A big difference between expression and call (the functions) is that the latter expects a character object and will evaluate it by looking for a named function in the symbol table.

When you say that processing both with the eval "works", you are not saying it produces the same results, right? The D function (call) has additional arguments that get substituted and restrict and modify the result. On the other hand evaluation of the expression-object substitutes the values into the symbols.

There seem to be "levels of evaluation":

expression(mean(1:10))
# expression(mean(1:10))
 call("mean" , (1:10))
# mean(1:10)
 eval(expression(mean(1:10)))
# [1] 5.5
 eval(call("mean" , (1:10)))
# [1] 5.5

One might have expected eval(expression(mean(1:10))) to return just the next level of returning a call object but it continues to parse the expression tree and evaluate the results. In order to get just the unevaluated function call to mean, I needed to insert a quote:

eval(expression(quote(mean(1:10))))
# mean(1:10)
Tepper answered 3/12, 2013 at 18:35 Comment(0)
M
3

From the documentation (?expression):

...an R expression vector is a list of calls, symbols etc, for example as returned by parse.

Notice:

R> class(func[[1]])
[1] "call"

When given an expression, D acts on the first call. If func were simply a call, D would work the same.

R> func2 <- substitute(2 * x * y + x^2)
R> class(func2)
[1] "call"
R> D(func2, 'x')
2 * y + 2 * x
Medawar answered 3/12, 2013 at 16:8 Comment(0)
A
0

Sometimes for the sake of consistency, you might need to treat both as expressions.

in this case as.expression comes in handy:

func <- expression(2*x*y + x^2)
funcDx <- as.expression(D(func, 'x'))
> class(func)
[1] "expression"
> class(funcDx)
[1] "expression"
Aestival answered 26/1, 2022 at 2:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.