22

在 Ruby中Integer === 5返回true. 同样String === "karthik"返回true.
但是,5 === Integer返回false. 和"karthik" === String
为什么运算符不可交换?

4

4 回答 4

37

简单的答案是:因为它没有意义。算子描述的关系是不可交换的,为什么算子应该是?

看看你自己的例子:5是一个Integer. 但是是Integer一个5?这甚至意味着什么?

===case subsumption operator,并且 subsumption 不通勤。

case 包含运算符使用等号,并且它通常被称为三元等号threequalscase equality运算符这一事实是非常不幸的,因为它不仅与相等绝对无关,而且它也不符合许多定律相等符合,例如传递性和您提到的交换性。

有关我的更多咆哮,===请参阅

于 2010-12-24T21:45:06.740 回答
7

一个非常简单的原因是is_a?类的关系不能是可交换的。考虑两个操作数都是类的情况:

Class === String

这将返回 true,因为String.is_a?(Class). 然而String === Class会返回假,因为Class.is_a?(String)是假的,这当然是应该的。

另一个原因是 的语义===取决于它的左操作数。这又有两个原因:a)在 ruby​​ 中,语义总是依赖于左操作数,因为左操作数是方法调用的接收者;b)它很有用,因此您可以在一个案例中使用例如类、范围和正则表达式具有预期语义的语句。

于 2010-12-24T16:17:41.607 回答
2

许多运算符不是可交换的。

===称为“案例相等运算符”,因为它在分支是案例时被调用。

这是很好和有用的:

foo = 42
case foo
when Integer
  # branches here
when String
  # etc...
end

如果它不是很有用

foo = Integer
case foo
when 42
# would branch here??
when 666
# etc...
end

请注意,在 Ruby 1.9 中,===Proc/lambda 上的运算符将调用该 Proc:

divisible_by_three = ->(x){x % 3 == 0}
divisible_by_three === 42 # => true

同样,在语句中非常有用case,但在相反的顺序中并不多。

于 2010-12-24T18:01:02.007 回答
1

它需要实现 case-when 比较

有非交换运算符是正常的。

/ - % [] . -> ^ << >> < <= > >= && || = += -= ,

碰巧,它===部分作为case-when运算符存在。这在 Ruby 中相当复杂,如果必须将其简化为可交换运算,就不可能如此。

于 2010-12-24T17:56:20.207 回答