在R中,引号和表达式有什么区别?

10
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))

expression(sin(x + y)) == quote(sin(x + y)) 中出现错误: 表达式无法进行比较。

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

它们看起来差不多。


1
如果您感兴趣,quoteexpression的C源代码可以在/src/main/coerce.c/src/main/builtin.c中找到。分别搜索这些文件中的do_quotedo_expression即可。 - jbaums
2个回答

16
  • expression 返回其参数作为未求值表达式的向量。
  • quote 将其参数作为未求值表达式返回。

试一下:

(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

另一个例子:

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)

2
就目前而言,这似乎对我来说是一条注释。改进建议:在什么情况下我们会使用quote但不是expression?反之亦然。唯一的区别是quote返回一个列表,而expression返回一个向量吗? 这里是r-help上同一主题的优秀讨论。链接 - MichaelChirico

1

@kohske已经回答得很好了,但为了强调一个表达式只是未求值表达式列表,例如由引用返回的表达式,带有class表达式:

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

一个表达式的模式不是"list"而是"expression",然而,与例如"data.frame"不同的是:
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

现在,不同的类别可能意味着非常不同的方法,但实际上至少在基本R中并没有太多这样的类别:

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

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

因此,将表达式视为未计算的表达式列表似乎是相当安全的。每当尝试像使用列表一样使用表达式时出现问题时,使用as.list将非常安全,例如:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接