【问题标题】:Strange syntax error involving block and ternary operator涉及块和三元运算符的奇怪语法错误
【发布时间】:2016-07-20 11:43:44
【问题描述】:

我试过类似这样的代码:

array = [1, 2, 3]
array.each do |i|
  i == 1 ? puts "foo" : puts "bar"
end

但我收到语法错误:

expecting keyword_do or '{' or '('

然后我尝试了这样的代码:

array = [1, 2, 3]
array.each do |i|
  puts i == 1 ? "foo" : "bar"
end

它成功了。

为什么会出现这个错误?这是一个错误吗?

我发现了https://bugs.ruby-lang.org/issues/10653 关于三元运算符和块的一个错误,但我不太了解。

我正在使用 ruby​​ 2.2.4

【问题讨论】:

  • 这绝对是您看到的错误。看起来这是 2.2 中引入的回归。对于“真实”代码,只需使用后者 - 三元运算符在用于赋值而不是控制流时更惯用。
  • @jjm 这不是一个错误,它与 ruby​​ 允许您省略方法调用的括号但仅当它们是该行的最后一项时才有关。由于三元是内联的,您将不得不更改为i == 1 ? puts("foo") : puts("bar"),据说第二个无论如何都是 DRYer。否则解释器会尝试处理puts("foo" : puts "bar"),这是无效的语法。
  • @engineersmnky 好的,你是对的——没有括号,语法总是假的。错误在于它报告了一些关于缺少 do 的信息,这令人困惑。
  • @jjm do 是有效的块语法,任何方法都可以传递一个块,它可能永远不会 callyield 给它。解析器不会进行这种区分,因此它会使用所有可能有效的选项来修复语法错误keyword_do or '{' or '('
  • 啊,没错。

标签: ruby block ternary-operator


【解决方案1】:

这不是错误,而是运算符优先级问题 i == 1 ? puts "foo" : puts "bar" 将 Ruby 读取为 i == 1 ? puts("foo" : puts "bar"),这没有任何意义。这是因为方法调用在所有运算符中的优先级最低

你应该自己把括号放在i == 1 ? puts("foo") : puts("bar")

【讨论】:

    【解决方案2】:

    看起来 Ruby 在评估这两个表达式时遇到了问题。

    尝试用括号括起来:

    array = [1, 2, 3]
    array.each do |i|
      i == 1 ? (puts "foo") : (puts "bar")
    end
    

    应该可以。

    【讨论】:

    • 这也是三元非常混乱的情况。在进行方法调用时,使用合适的if,把逻辑打断,说的很清楚。
    【解决方案3】:

    调用方法时使用括号:

    array = [1, 2, 3]
    array.each do |i|
      i == 1 ? puts("foo") : puts("bar")
    end
    

    显式优于隐式

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-19
      • 2012-10-01
      • 1970-01-01
      • 2013-10-29
      • 2014-06-01
      • 2016-07-14
      • 1970-01-01
      相关资源
      最近更新 更多