【发布时间】:2010-12-24 16:11:09
【问题描述】:
在 Ruby 中 Integer === 5 返回 true。同样String === "karthik" 返回true。
但是,5 === Integer 返回false。还有"karthik" === String.
为什么算子不可交换?
【问题讨论】:
标签: ruby equality commutativity
在 Ruby 中 Integer === 5 返回 true。同样String === "karthik" 返回true。
但是,5 === Integer 返回false。还有"karthik" === String.
为什么算子不可交换?
【问题讨论】:
标签: ruby equality commutativity
简单的答案是:因为它没有意义。算子描述的关系是不可交换的,为什么要算子呢?
看看你自己的例子:5 是一个Integer。但是Integer 是5 吗?这甚至意味着什么?
=== 是case 包含运算符,并且包含不可以交换。
case 包含运算符使用等号,并且它通常被称为 三等号、threequals 或 case equality 运算符这一事实是非常不幸的,因为它不仅与平等绝对无关,而且它也不符合许多平等所遵循的规律,例如传递性和你提到的交换性。
有关我对=== 的更多抱怨,请参阅
【讨论】:
一个非常简单的原因是类的is_a? 关系不能是可交换的。考虑两个操作数都是类的情况:
Class === String
这将返回 true,因为 String.is_a?(Class)。但是String === Class 会返回 false,因为Class.is_a?(String) 是 false,这当然是应该的。
另一个原因是=== 的语义取决于它的左操作数。这又有两个原因:a)在 ruby 中,语义总是依赖于左操作数,因为左操作数是方法调用的接收者;b)它很有用,所以你可以使用例如具有预期语义的 case 语句中的类、范围和正则表达式。
【讨论】:
许多运算符是不可交换的。
=== 被称为“case 相等运算符”,因为它在分支是 case 时被调用。
这是很好和有用的:
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 运算符存在。这在 Ruby 中相当复杂,如果必须将其简化为可交换运算,那就不可能了。
【讨论】: