Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between quote and expression in R

Tags:

r

gettypes = function(x) {paramx = substitute(x); print(typeof(paramx)); print(class(paramx)); print(mode(paramx))}
gettypes(expression(sin(x+y)))
# [1] "language"
# [1] "call"
# [1] "call"
gettypes(quote(sin(x+y)))
# [1] "language"
# [1] "call"
# [1] "call"
expression(sin(x+y)) == quote(sin(x+y))

Error in expression(sin(x + y)) == quote(sin(x + y)) : comparison is not allowed for expressions

identical(expression(sin(x+y)), quote(sin(x+y)))
# [1] FALSE
x = 1
y = 2
eval(expression(sin(x+y)))
# [1] 0.14112
eval(quote(sin(x+y)))
# [1] 0.14112

They look pretty much the same.

like image 685
qed Avatar asked Oct 23 '14 15:10

qed


2 Answers

  • expression returns its arguments as a vector of unevaluated expressions.
  • quote returns its argument as an unevaluated expression.

Try this:

(e1 <- quote(sin(x+y)))
# sin(x + y)
(e2 <- expression(sin(x+y)))
# expression(sin(x + y))
str(e1)
# language sin(x + y)
str(e2)
# expression(sin(x + y))
str(e2[[1]])
# language sin(x + y)
all.equal(e1, e2)
# [1] "Modes of target, current: call, expression" "target, current do not match when deparsed"
all.equal(e1, e2[[1]])
# [1] TRUE

Another example:

e2 = expression(sin(x+y), x+y)
e2
# expression(sin(x + y), x + y)
e2[1]
# expression(sin(x + y))
e2[2]
# expression(x + y)
like image 102
kohske Avatar answered Sep 23 '22 06:09

kohske


@kohske answered very well already, but to hammer the nail that an expression is really ONLY a list of unevaluated expressions such as returned by quote, with a class expression :

x <- list(quote(2*3),quote(4*5))
class(x) <- "expression"
identical(x, expression(2*3, 4*5))
# [1] TRUE

The mode of an expression is not "list" but "expression" however, unlike data.frame for example :

e <- expression(2*3, 4*5)
class(e)
# [1] "expression"
mode(e)
# [1] "expression"
class(unclass(e))
# [1] "expression"
is.list(e)
# [1] FALSE


class(iris)
# [1] "data.frame"
mode(iris)
# [1] "list"
class(unclass(iris))
# [1] "list"
is.list(iris)
# [1] TRUE

Now the different class could mean very different methods but in practice there are not many of them at least in base R :

methods(class="expression")
# [1] coerce Ops   

methods(class="list")
# [1] all.equal     as.data.frame coerce        Ops           relist        type.convert  within

So it seems rather safe to consider an expression as a list of unevaluated expressions, and whenever an issue arises when trying to use expressions as we would use a list, as.list will be quite safe to use, for example :

with(expression(a=2*3, 4*5),a)
# Error in eval(substitute(expr), data, enclos = parent.frame()) : 
#   invalid 'envir' argument of type 'expression'
with(as.list(expression(a=2*3, 4*5)),a)
# 2 * 3
like image 22
Moody_Mudskipper Avatar answered Sep 25 '22 06:09

Moody_Mudskipper