【问题标题】:When does operator associativity matter?运算符关联性何时重要?
【发布时间】:2013-11-30 13:02:41
【问题描述】:

大多数编程语言都有一个二元运算符的优先级和关联性表。在某些情况下,关联性很重要,例如(a - b) - c != a - (b - c).

但是,对于像 && 这样的关联运算符,这似乎无关紧要,但大多数语言将其列为左关联。

(a && b) && ca && (b && c) 之间是否存在实际差异?

【问题讨论】:

  • 想想当abc 是具有副作用的函数时会发生什么。
  • @Juhana:会发生什么?据我所知,没有什么不同。
  • @Mehrdad,副作用会改变评估结果,导致不同的结果。
  • @Juhana:这是一个完全不同的论点,我们不要混淆它们。你是对的,为&& 定义不同的定义是没有用的...但是这在技术上没有任何问题。我的观点只是它们不会影响评估顺序。

标签: c syntax programming-languages operators associativity


【解决方案1】:

我不敢相信有这么多错误(已删除)的答案……也许我应该回答这个问题。

首先,precedence != associativity != evaluation order

现在我们已经解决了这个问题:在某些情况下,关联性很重要。
对于a + b + c,当abc 是浮点数而不是整数时很重要,因为根据项的分组方式,舍入误差的累积方式会有所不同。

对于 &&|| 的特殊情况,只要它们没有重载(这仅在 C++ 中可能,而不是 C 中可能)无关紧要,但是语言仍然定义一个只是为了保持一致性——因此代码的“树”表示(基于语法)是唯一的。这也对 C++ 有利,因为现在重载 &&|| 的含义并不模糊。

【讨论】:

    【解决方案2】:

    添加到@Mehrdads@ 答案(我赞成):

    如果您曾经构建过解析器,您会注意到您的运算符必须具有关联性,否则

    a && b && c
    

    只是一个语法错误。假设以上不应该是语法错误,你必须决定它是否应该意味着:

    (a && b) && c
    

    a && (b && c)
    

    你不能只说:我不在乎。

    【讨论】:

    • 对。大多数解析器都使用前者。我注意到如果我使用后者,它会使解析器稍微简单一些,因此我的问题是确保它不会破坏任何东西。
    • 这真的取决于运营商@rwallace。在许多语言中,求幂不是右结合吗?在 Haskell 中,也有许多右结合运算符。但可以肯定的是,没有人想要 a/b/2 意思是 2a/b
    • 实际上在这种情况下,只要定义了 && 的操作顺序(例如,总是先计算左操作数),您就不必关心。您可以从a && ??? 开始,然后从评估a 开始,而无需“偷看”接下来的内容。这实际上是一个要求,否则对短路运算符的 RHS 会产生意外的依赖。可能有用于解析的标准技术,但即使是那些也主要是按照惯例。逐行解释器可以评估这样的表达式,并且只有在评估 a 后才能继续解析。
    • @CPerkins 你可以这样做,但是你会实现正确的关联性,简单明了。我们必须在左结合性和右结合性之间进行选择只是因为我们在这里处理二元运算符这一事实。
    • @Ingo 只是 Mehrdad 的回答说“没关系”,然后你的回答说它是“添加”到 Mehrdad 的,然后与之相矛盾说“必须决定”,并且“你不能只说:我不在乎。那是什么?你的答案只考虑了涉及多个运算符的关联性,但 && 的特殊之处在于单个运算符(它什么都没有与关联性有关)要求首先评估左操作数。
    猜你喜欢
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 2017-05-22
    • 2015-08-02
    • 2016-07-19
    • 1970-01-01
    • 2021-05-05
    相关资源
    最近更新 更多