【问题标题】:Why is this not a syntax error?为什么这不是语法错误?
【发布时间】:2026-02-15 16:40:01
【问题描述】:

如果我这样做:

(false true)

正如我所料,它因语法错误而失败。但如果我这样做:

(false
 true)

代码被执行,它丢弃第一个条件并返回第二个条件的结果。

这被认为是错误还是功能?

【问题讨论】:

  • 我知道必须有一个简单的解释。您应该将此作为真实答案发布,并为自己争取一些功劳。 :-)

标签: ruby syntax


【解决方案1】:

行尾是可选的,因此在这种情况下,返回导致解析器将其解释为:

(false; true)

计算结果为:

(true)

如果这些是方法调用,那么两者都会被评估,但只会发出最后一个。例如:

x = (p "hello"
p "world"
2)

这将输出“hello”和“world”,x 等于 2

【讨论】:

    【解决方案2】:

    括号用于分组,换行符用作表达式分隔符。因此,您在这里所拥有的只是一组两个表达式。没有什么可以拒绝的。

    这很有用,因为这个众所周知的习语:

    def foo(bar = (bar_set = true; :baz))
      if bar_set
        # optional argument was supplied
      end
    end
    

    在 Ruby 中根本没有其他方法可以确定是否提供了可选参数。

    基本上,这在存在副作用的情况下变得有趣,例如在我的示例中分配一个变量或在@32bitkid 的示例中打印到屏幕上。在您的示例中,没有副作用,这就是为什么您看不到实际上发生了什么。

    【讨论】:

    • 其实这个成语对我来说是新的,所以我很感谢你的回答!
    • @L2G:它不经常使用,但是有一些标准协议需要区分是否提供了可选参数。 inject 就是一个例子。通常它是用 C 或 Java 或 C# 实现的,具有对解释器内部的特权访问,这使得检查可选参数的存在变得容易。但是如果你想在纯 Ruby 中复制它的行为,你就不得不求助于这样的技巧。
    【解决方案3】:

    如果你有警告,Ruby 可以给你一个警告。

    $VERBOSE = true
    def foo
      (false
       true)
    end
    

    给你

    (irb):3: warning: unused literal ignored
    

    在 Ruby 1.9.1 补丁级别 378 和 Ruby 1.8.7 补丁级别 330 中。

    请参阅How can I run all Ruby scripts with warnings?,了解如何运行所有带有警告的 Ruby 脚本。

    【讨论】:

      最近更新 更多