有两个很好的理由说明为什么Ruby 1.8不支持某些类型的重载,例如||
/ or
,&&
/ and
,!
/ not
,?:
:
nil
和false
视为false。第一个原因不适用于!
/ not
,但第二个原因仍然适用。这并不像你只使用!
引入自己类型的布尔类对象,而&&
/ ||
仍然是硬编码的。对于其他用途,已经存在具有~
/ &
的互补运算符|
。
我可以想象有很多代码期望!obj
与obj ? false : true
同义,而!!obj
与obj ? true : false
同义 - 我甚至不确定代码是怎么回事处理在布尔上下文中求值为true的对象,但!
处理为非假的对象。
Ruby似乎不打算引入对其他错误值的支持。 Ruby stdlib中的任何内容似乎都不会覆盖!
,所以我没有找到任何示例。
它是否有一些非常好的用途我错过了?
答案 0 :(得分:1)
自回复。到目前为止我找到了一个合理的用法。我可以通过几行来破解它在1.9.2中的工作:
describe "Mathematics" do
it "2 + 2 != 5" do
(2+2).should != 5
end
end
在1.9.2 Ruby之前,这转换为:
describe "Mathematics" do
it "2 + 2 != 5" do
((2+2).should == 5) ? false : true
end
end
但是当返回值被抛弃时,我们没有办法区分== 5
和!= 5
之间没有问过Ruby的块的解析树。 PositiveOperatorMatcher#==(5)
只会引发ExpectationNotMetError
异常,那就是它。似乎should !~ /pattern/
,should !be_something
等也可以发挥作用。
这比(2+2).should_not == 5
有所改善,但并不是很大。并且没有办法进一步破解它以获得(2+2).should be_even or be_odd
。
当然,正确的做法是asking Ruby for parse tree and macro-expanding that。或者在Ruby解释器中使用调试钩子。是否有比这更好的用例?
顺便说一下,在翻译旧版!
/ !=
时,允许覆盖!~
是不够的。要使!((2+2).should == 5)
工作#==
,在调用!
之前无法引发异常。但是如果#==
失败并且!
没有运行,则执行将继续执行。我们将能够在块退出后将断言报告为失败,但是在第一次失败后执行测试的成本。 (除非我们在断言失败后打开ruby调试挂钩,看看下一个方法调用是!self
,还是类似的东西)