Ruby TrueClass单管道

its*_*lay 7 ruby

来自文档:http://ruby-doc.org/core-2.2.0/TrueClass.html#method-i-7C

true |  puts("or")
true || puts("logical or")

# produces:

or
Run Code Online (Sandbox Code Playgroud)
  • 你能解释什么时候"单管"有用吗?
  • 有什么不同?

(仅在TrueClass上下文中(不是ArrayFixnum上下文)

Ray*_*oal 8

很难说为什么定义TrueClass了一个#|方法.

事实上它是一个方法确实意味着它的两个"操作数"被评估然后组合,这就是"or"输出字符串的原因.双管是一个特殊的构造:如果第一个操作数是真的,它将不会计算第二个操作数.因此,作为一种进行布尔计算的方法,单个管道看起来毫无用处.

现在,运算符更有意义Fixnum:它执行与C,Java等中所见的相同的按位OR.

例如:

>> 133|243
=> 247
Run Code Online (Sandbox Code Playgroud)

现在Java由于某种原因,|在布尔值上超载成为非短路运算符.也许Ruby正在做"我也是"?Ruby似乎不太可能想在这里复制Java.

这种情况更可能是因为

true | e
Run Code Online (Sandbox Code Playgroud)

评估为

e
Run Code Online (Sandbox Code Playgroud)

对于任何e,Ruby允许你将一堆真正的表达链接在一起.也许

true | e1 | e2 | e3 | e4
Run Code Online (Sandbox Code Playgroud)

看起来比凉爽

e1
e2
e3
e4
true
Run Code Online (Sandbox Code Playgroud)

甚至

e1; e2; e3; e4; true
Run Code Online (Sandbox Code Playgroud)

另一种可能性是它允许你将带有副作用的布尔生成表达式链接在一起.

f(x1) | f(x2) | f(x3) | f(x4)
Run Code Online (Sandbox Code Playgroud)

并返回是否产生任何功能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
Run Code Online (Sandbox Code Playgroud)

当然,这仍然是一个蹩脚的尝试,因为你得到同样的效果:

>> [f(1),f(2),f(3),f(4)].any?
1
2
3
4
=> true
Run Code Online (Sandbox Code Playgroud)

我怀疑,但我不是100%肯定,在代数意义上包含运算符是为了某种"完整性".布尔代数具有AND或OR,并且||实际上并不是具有急切评估语义的经典意义上的方法.所以也许它因为这个原因而被抛入,并且,如果任何程序员碰巧找到它的用途,那么很棒.但是,在多年的编程中,我从未见过任何不短路的实用理由.

事实上我认为,如果有人要编写依赖于布尔上下文中第二个参数的评估的代码(即使用#|),那么这样的代码会让人感到困惑 - 当然不会引用透明的,因为它会依赖副作用---因此应该重写.


Mik*_*iet 8

当您不需要急切评估声明时,它非常有用.

例如,如果你有一些方法,它们做了一些有用的事情并返回true/ false作为结果,并且只有在任何这些方法返回时才应该调用另一个方法,true使用它是很有用的|:

def action1
  # do something, returns true/false
end

def action2
  # do something, returns true/false
end

def result_action
  # do something 
end

result_action if action1 | action2
Run Code Online (Sandbox Code Playgroud)

如果你使用logical ||而不是if action1返回true,action2则不会被调用(result_action尽管会被调用)