很难说为什么TrueClass 定义了#| method。
它是一个方法的事实确实意味着它的两个“操作数”都被评估然后组合,这就是输出字符串"or"的原因。双管道是一种特殊的结构:如果第一个操作数为真,它不会计算第二个操作数。因此,作为一种进行布尔计算的方法,单管道看起来毫无用处。
现在,Fixnum 上的运算符更有意义:它执行与 C、Java 等中相同的按位 OR。
例如:
>> 133|243
=> 247
现在,出于某种原因,Java 将布尔值上的 | 重载为非短路运算符。也许 Ruby 正在做“我也是”? Ruby 似乎不太可能在这里复制 Java。
更有可能是因为
true | e
评估为
e
对于任何 e,Ruby 允许您将一堆真实的表达式链接在一起。也许
true | e1 | e2 | e3 | e4
看起来比
e1
e2
e3
e4
true
甚至
e1; e2; e3; e4; true
另一种可能性是它允许您将产生布尔值的表达式与副作用链接在一起。
f(x1) | f(x2) | f(x3) | f(x4)
并返回是否有任何函数产生true。这是一个人为的例子:
>> def f(x);puts x;return x==2;end
=> :f
>> f(1) || f(2) || f(3) || f(4)
1
2
=> true
>> f(1) | f(2) | f(3) | f(4)
1
2
3
4
=> true
当然,这仍然只是一个蹩脚的尝试,因为你得到了同样的效果:
>> [f(1),f(2),f(3),f(4)].any?
1
2
3
4
=> true
我怀疑,但不是 100% 肯定,包含该运算符是为了代数意义上的某种“完整性”。布尔代数具有 AND 或 OR,而 || 并不是具有热切求值语义的经典意义上的真正方法。所以也许它是因为这个原因而被扔进去的,而且,如果任何程序员碰巧找到了它的用途,那就太好了。但在多年的编程中,我从未见过任何不短路的实用理由。
事实上,我认为如果有人编写的代码依赖在布尔上下文中对第二个参数的评估(即,使用#|),那么这样的代码会令人困惑--- 而且肯定不是引用透明的,因为它会依赖副作用 --- 因此应该重写。