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

在的标准R帮助页面上,它们不包括函数调用,这在我看来似乎相当草率。这给我带来了一些问题,所以我决定对
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()