R中函数调用的优先级
在的标准R帮助页面上,它们不包括函数调用,这在我看来似乎相当草率。这给我带来了一些问题,所以我决定对R中函数调用的优先级,r,operator-precedence,function-calls,R,Operator Precedence,Function Calls,在的标准R帮助页面上,它们不包括函数调用,这在我看来似乎相当草率。这给我带来了一些问题,所以我决定对substitute使用试错法,并发现优先级似乎介于[[[/code>和^之间: > substitute(a^b())[[1]] `^` > substitute(a[b]())[[1]] a[b] 在中缀表示法中,它们是(^a(b())和([ab())(将调用运算符表示为())。在简单的英语中,第一个示例显示在参数a和b()上调用指数函数而在第二个示例中,最终结果是调用函数a[b
substitute
使用试错法,并发现优先级似乎介于[[[/code>和^
之间:
> substitute(a^b())[[1]]
`^`
> substitute(a[b]())[[1]]
a[b]
在中缀表示法中,它们是(^a(b())
和([ab())
(将调用运算符表示为()
)。在简单的英语中,第一个示例显示在参数a
和b()上调用指数函数
而在第二个示例中,最终结果是调用函数a[b]
这种优先级在任何情况下都适用吗?函数调用的优先级不是恒定的似乎很奇怪,但如果它确实是恒定的,那么它就不会包含在上面的帮助页面中,这是没有意义的。可能不是“优先级”问题,而是解析问题。(但是在考虑了它之后,它看起来确实像是优先顺序,并且是由完成“[”和“]”之间所有参数的参数匹配的需要引起的)首先,解析树被构造为:
`^`
/ \
a b
> substitute(a^b())[1]
`^`()
> substitute(a^b())[[1]]
`^`
> substitute(a^b())[[2]]
a
> substitute(a^b())[[3]]
b()
在第二个实例中,它被构造为
a[b]
/
NULL
但第一个元素也有一个结构:
`[`
/ \
a b
> substitute(a[b]())[[1]][[1]]
`[`
> substitute(a[b]())[[1]][[2]]
a
> substitute(a[b]())[[1]][[3]]
b
我认为歧义可能是因为这两个函数(^
和[
)而产生的,只有后者才能真正交付函数,因此需要先处理它。对a^b
的求值结果永远不可能是函数,因此按^
(a,b())进行处理是有意义的
当涉及到让这样的东西真正起作用时,我认为第二个不是很有用。为了从工作区中提取和替换,您需要额外的提取步骤:
b <- list(mean)
> eval( substitute(a^b(1:10) , list(a=2) ))
Error in eval(expr, envir, enclos) : could not find function "b"
> eval( substitute(a^b[[1]](1:10) , list(a=2) ))
[1] 45.25483
hadley相当圆滑。函数调用的优先级是常量
R非常像lisp,在引擎盖下。
比如,SEXP是一个元组(list),其中元组的第一个元素([[1]]]
)是运算符,其余元素(通常是其他SEXP)是运算符的参数
当你写作时
paste("a",1 + 2)
R理解
(`paste`,"a",(`+`, 1, 2))
当您运行substitute时,您将获得SEXP(尽管它们像R代码一样打印),并且(最外层)SEXP的第一个元素是将应用于表达式中的最后一个运算符,即最低优先级
您可能知道,您可以使用以下方式查看表达式的各个部分:
> str(as.list(quote(a^b())))
List of 3
$ : symbol ^
$ : symbol a
$ : language b()
将此理解应用于示例中的优先级
a^b()
的最后一个运算符是什么?
我们把它逐步考虑为
替换并评估a
替换并评估b
计算(步骤的结果)2
,不带任何参数(这称为调用)
替换并评估^
使用参数1
和3
因此,最后一个运算符是名为^
接下来,a[b]()
的最后一个运算符是什么?
替换并评估a
替换并评估b
替换并评估[
使用参数(步骤结果)1
和(步骤结果)2
评估(步骤的结果)4
在这种情况下(步骤的结果)4
具有方便的名称a[b]
因此,最后一个运算符是对a[b]
的调用(无参数求值)
编辑:警告
我在这里简化了实际情况,因为R的一个特点是,函数参数作为未赋值(环境、表达式)对传递给函数(运算符),(而不是通过引用或值),虽然“提交”顺序与上述大致相同,但实际的分派顺序实际上是相反的,甚至遗漏了步骤。不过,您不必担心这一点。在第一个问题的表达式中去掉了额外的右括号,但也试图去掉[[1]]
因为表达式中并不是这样。您同意吗?请参见pryr::ast()
自动绘制树
> str(as.list(quote(a^b())))
List of 3
$ : symbol ^
$ : symbol a
$ : language b()