3 оператора равенства или равенства - PullRequest
20 голосов
/ 24 декабря 2010

В Ruby Integer === 5 возвращает true. Аналогично String === "karthik" возвращает true.
Однако 5 === Integer возвращает false. И "karthik" === String.
Почему оператор не коммутативный?

Ответы [ 4 ]

34 голосов
/ 25 декабря 2010

Простой ответ: потому что это не имеет смысла.Отношения, которые описывает оператор, не являются коммутативными, почему оператор должен быть?

Просто посмотрите на свои собственные примеры: 5 - это Integer.Но Integer а 5?Что это означает * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * '' * '' '.Оператор подстановки в регистре использует знаки равенства и то, что его обычно называют оператором тройного равенства , threequals или case equality, является ужасно неудачным, поскольку он не только не имеет абсолютно ничего имеет отношение к равенству, но оно также не соответствует многим законам, которым соответствует равенство, таким как транзитивность и, как вы упомянули, коммутативность.

Подробнее о моих разглагольствованиях о === см.

7 голосов
/ 24 декабря 2010

Одна очень простая причина в том, что отношение is_a? для классов просто не может быть коммутативным.Рассмотрим случай, когда оба операнда являются классами:

Class === String

Это вернет true, потому что String.is_a?(Class).Однако String === Class вернет false, потому что Class.is_a?(String) равно false, и это, конечно, так и должно быть.

Другая причина заключается в том, что семантика === зависит от его левого операнда.Это опять-таки имеет две причины: а) в ruby ​​семантика всегда зависит от левого операнда, поскольку левый операнд является получателем вызова метода и б) он полезен, поэтому вы можете использовать, например, классы, диапазоны и регулярные выражения в случаеоператор с намеченной семантикой.

2 голосов
/ 24 декабря 2010

Многие операторы не являются коммутативными.

=== называется "оператором равенства регистра", потому что он вызывается, когда ветвление является регистром.

Приятно и полезно, что:

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, но не слишком в обратном порядке.

1 голос
/ 24 декабря 2010

для этого нужно реализовать случай-сравнения

Нормально иметь некоммутативные операторы.

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

И, как это бывает, === существует частично как оператор case-when . Это довольно сложно в Ruby, и этого не могло быть, если бы его пришлось упростить до коммутативного оп.

...