在 Ruby中Integer === 5
返回true
. 同样String === "karthik"
返回true
.
但是,5 === Integer
返回false
. 和"karthik" === String
。
为什么运算符不可交换?
4 回答
简单的答案是:因为它没有意义。算子描述的关系是不可交换的,为什么算子应该是?
看看你自己的例子:5
是一个Integer
. 但是是Integer
一个5
?这甚至意味着什么?
===
是case subsumption operator,并且 subsumption 不通勤。
case 包含运算符使用等号,并且它通常被称为三元等号threequals
或case equality
运算符这一事实是非常不幸的,因为它不仅与相等绝对无关,而且它也不符合许多定律相等符合,例如传递性和您提到的交换性。
有关我的更多咆哮,===
请参阅
一个非常简单的原因是is_a?
类的关系不能是可交换的。考虑两个操作数都是类的情况:
Class === String
这将返回 true,因为String.is_a?(Class)
. 然而String === Class
会返回假,因为Class.is_a?(String)
是假的,这当然是应该的。
另一个原因是 的语义===
取决于它的左操作数。这又有两个原因:a)在 ruby 中,语义总是依赖于左操作数,因为左操作数是方法调用的接收者;b)它很有用,因此您可以在一个案例中使用例如类、范围和正则表达式具有预期语义的语句。
许多运算符不是可交换的。
被===
称为“案例相等运算符”,因为它在分支是案例时被调用。
这是很好和有用的:
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
,但在相反的顺序中并不多。
它需要实现 case-when 比较
有非交换运算符是正常的。
/ - % [] . -> ^ << >> < <= > >= && || = += -= ,
碰巧,它===
部分作为case-when运算符存在。这在 Ruby 中相当复杂,如果必须将其简化为可交换运算,就不可能如此。