【问题标题】:Why does the expression (true == true == true) produce a syntax error?为什么表达式 (true == true == true) 会产生语法错误?
【发布时间】:2018-06-17 23:45:43
【问题描述】:

鲁比

true == true == true

语法错误,意外的 tEQ

对比JavaScript

true == true == true
// => true

对比C

1 == 1 == 1
// => 1

【问题讨论】:

  • 有趣的是,似乎只有等式运算符(=====!=)可以做到这一点。甚至 <> 也能正确解析,然后像您期望的那样产生运行时错误。另外,onlysources 我能找到哪个声称拥有完整的 Ruby 语法似乎表明这种语法是允许的。
  • 它也可以像这样不带括号,显式调用 true .== true .== true
  • 我想知道有多少其他人难以置信地将失败的代码输入到 irb 中并期望得到不同的结果?
  • stackoverflow.com/a/21060235/2864740 - == 在答案中被列为 not-associative (A=N),这意味着这样的 X==Y==Z 产生式无效(关联性是什么“在相同优先级的运算符周围添加隐式括号”)。问题中有许多链接可能会回到可以清楚引用的更“官方来源”。 (这个问题更多的是关于该问题/答案中语法规则的特定子集/应用。)
  • @SilvioMayolo 根据上面的答案,< 和朋友 是左关联的.. 所以应该解析(并且“工作”,给定有效的运行时输入)。我不确定为什么 < 会关联而 == 不会关联的语法合理性是什么,尽管改变可能会打破很多期望..

标签: ruby syntax-error operators operator-precedence associativity


【解决方案1】:

== 方法没有定义关联方向,它控制评估其参数的运算符的顺序,与 ===!==~<=> 方法相同(所有其中具有相同的优先级并排他地形成一个单独的优先级组。

Documentation

因此,如果上述列表中的多个运算符连续链接在一起,则应通过任一方式明确设置评估顺序

  • 括号():

    (true == true) == true # => true
    true == (true == true) # => true
    
  • 或点运算符.对于一行中的最后一个相等检查可以省略):

    true .== true == true # => true
    

【讨论】:

  • 我很想知道为什么,但我认为这超出了问题和您的答案的范围。
  • @CarySwoveland 可能是因为如果 == 是左关联的,1 == 1 == 1 在 Ruby 中的计算结果为 false,这可能会导致几个错误。而且它也没有多大意义——第三个操作数唯一合理的值是truefalse,即a == b == truea == b == false,可以表示为a == ba != b。跨度>
  • @Stefan:只有一种情况可以以一种有意义的方式使用它,尽管我必须说这个例子有点牵强:== 可以在自定义类中被覆盖,因此相等性检查可以返回除 truefalse 之外的其他内容(例如,nil
  • @CarySwoveland 我认为可以从语言设计者的角度解决,例如this
  • javascript-truthiness-in-boolean-to-numbers-comparison 为什么我们都应该停止在比较整数与整数或布尔值的 javascript 示例中使用 0 或 1
【解决方案2】:

TL;DR 语法意味着所有 3 个值都是相等的,这不是它在 javascript 或 C 中所做的,因此通过 ruby​​ 给出语法错误,为将来实现这一点打开了大门。

如果我正确理解了这个问题,value_a == value_b == value_c 应该只在它们都相等的情况下返回 true,使用 == 作为比较运算符,如本方法所示

# version 1
def compare_3_values(a, b, c)
  a == b && a == c && b == c
end

还有另一个可能的预期结果。实现这一点,如上一个答案所示:

#version 2
def compare_3_values(a, b, c)
  (a == b) == c
end

结果是天壤之别。

JavaScript 总是使用版本 2,因为第 3 项总是与真或假进行比较(如果第 3 项是整数,则为 0 或 1),这就是为什么 false == false == true 返回 true。

好消息是,因为 ruby​​ 给出了语法错误,所以它是唯一可以在不破坏每个人的代码的情况下实现这一点的语言。

对于任何其他语言,它会破坏如此多的代码,即使它在以后的主要版本中实现,也需要一个标志/设置来在未来几年内打开或关闭它,因此它永远不值得.

Ruby 中一些有趣的结果

false .== false == true
=> true

false .== true == false
=> true

true .== false == false
=> true

false .== false == false
=> false

true .== true == false
false

在 javascript 中

false == false == true
=> true

false == true == false
=> true

true == false == false
=> true

false == false == false
=> false

true == true == false
=> false

编辑也在 C 中测试,其行为类似于 JavaScript,因为它将前两个值的结果与第三个值进行比较

【讨论】:

    【解决方案3】:

    first answer 非常好,但以防万一它不完全清楚(人们问为什么),这里还有几个例子。


    在 C 中,== 运算符是从左到右的关联运算符,布尔值表示为 1(真)和 0(假),因此第一个 1 == 1 计算结果为 1(真),然后你正在用第二个表达式评估第一个表达式的结果。你可以试试:

    2 == 2 == 2 // => 0
    

    在 C 中,计算为:

    (2 == 2) == 2
    1 == 2 // => 0
    

    在 Javascript 中,与 C 类似,== 是从左到右关联的。这次让我们尝试使用 0(尽管 C 中的相同示例也可以):

    0 == 0 == 0
    false
    

    再次:

    0 == 0 == 0
    true == 0 // => false
    

    在 Ruby 中 == 没有关联属性,即。它不能在单个表达式中多次使用,因此无法评估该表达式。为什么做出这个决定是语言作者的问题。此外,Ruby 没有将数字 1 定义为布尔值,因此 1 == true 的计算结果为 false。

    second answer 指出 Ruby 中有一些“奇怪”的情况,但它们都按预期进行评估:

    (1 == 1) == 1
    true == 1 # => false
    
    1 == (1 == 1)
    1 == true # => false
    
    1 .== 1 == 1
    (1 == 1) == 1
    true == 1 # => false
    
    false .== false == true
    (false == false) == true
    true == true # => true
    
    false .== true == false
    (false == true) == false
    false == false # => true
    
    true .== false == false
    (true == false) == false
    false == false # => true
    
    false .== false == false
    (false == false) == false
    true == false # => false
    
    true .== true == false
    (true == true) == false
    true == false # => false
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-28
      • 2013-02-02
      • 1970-01-01
      • 2016-09-17
      • 1970-01-01
      • 2017-07-29
      • 1970-01-01
      相关资源
      最近更新 更多