【发布时间】:2026-02-15 16:40:01
【问题描述】:
如果我这样做:
(false true)
正如我所料,它因语法错误而失败。但如果我这样做:
(false
true)
代码被执行,它丢弃第一个条件并返回第二个条件的结果。
这被认为是错误还是功能?
【问题讨论】:
-
我知道必须有一个简单的解释。您应该将此作为真实答案发布,并为自己争取一些功劳。 :-)
如果我这样做:
(false true)
正如我所料,它因语法错误而失败。但如果我这样做:
(false
true)
代码被执行,它丢弃第一个条件并返回第二个条件的结果。
这被认为是错误还是功能?
【问题讨论】:
行尾是可选的,因此在这种情况下,返回导致解析器将其解释为:
(false; true)
计算结果为:
(true)
如果这些是方法调用,那么两者都会被评估,但只会发出最后一个。例如:
x = (p "hello"
p "world"
2)
这将输出“hello”和“world”,x 等于 2
【讨论】:
括号用于分组,换行符用作表达式分隔符。因此,您在这里所拥有的只是一组两个表达式。没有什么可以拒绝的。
这很有用,因为这个众所周知的习语:
def foo(bar = (bar_set = true; :baz))
if bar_set
# optional argument was supplied
end
end
在 Ruby 中根本没有其他方法可以确定是否提供了可选参数。
基本上,这在存在副作用的情况下变得有趣,例如在我的示例中分配一个变量或在@32bitkid 的示例中打印到屏幕上。在您的示例中,没有副作用,这就是为什么您看不到实际上发生了什么。
【讨论】:
inject 就是一个例子。通常它是用 C 或 Java 或 C# 实现的,具有对解释器内部的特权访问,这使得检查可选参数的存在变得容易。但是如果你想在纯 Ruby 中复制它的行为,你就不得不求助于这样的技巧。
如果你有警告,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 脚本。
【讨论】: