=== vs. == в Ruby - PullRequest
       2

=== vs. == в Ruby

66 голосов
/ 06 августа 2010

В Ruby, в чем разница между == и ===? RDoc говорит

Case Equality - для класса Object, фактически то же самое, что и вызов # ==, но обычно переопределяется потомками для обеспечения содержательной семантики в операторах case.

Является ли #== таким же, как ==?И не могли бы вы привести пример того, когда / как это используется в операторах case?

Ответы [ 3 ]

124 голосов
/ 06 августа 2010

Два действительно не имеют ничего общего друг с другом. В частности, #== является оператором равенства, а #=== не имеет ничего общего с равенством. Лично я считаю весьма прискорбным, что #=== выглядит так же, как #==, использует знак равенства и часто называется оператором равенства , , оператором тройного равенства или оператор тройного оператора , когда он действительно не имеет ничего общего с равенством.

Я звоню #=== оператор подстановки падежа (это лучшее, что я могу придумать, я открыт для предложений, особенно от носителей английского языка).

Лучший способ описать a === b - это "если у меня есть ящик с надписью a, имеет ли смысл в него ставить b?"

Так, например, Module#=== проверяет, является ли b.is_a?(a). Если у вас Integer === 2, имеет ли смысл поместить 2 в коробку с надписью Integer? Да, это так. А как насчет Integer === 'hello'? Очевидно, нет.

Другой пример - Regexp#===. Это тесты на совпадение. Имеет ли смысл ставить 'hello' в поле с надписью /el+/? Да, это так.

Для коллекций, таких как диапазоны, Range#=== определяется как проверка принадлежности: имеет смысл поместить элемент в поле, помеченное коллекцией, если этот элемент находится в коллекции.

Итак, вот что делает #===: он проверяет, может ли аргумент быть включен в получатель.

Какое это имеет отношение к case выражениям? Простой:

case foo
when bar
  baz
end

совпадает с

if bar === foo
  baz
end
10 голосов
/ 06 августа 2010

Да, под #== документы означают «метод экземпляра == текущего объекта».

=== используется в выражениях case как таковых:

case obj
when x
  foo
when y
  bar
end

То же, что и

if x === obj
  foo
elsif y === obj
  bar
end

Некоторыми классами, которые определяют свои ===, являются Range (для действия, подобного include?), Class (для действия, подобного obj.is_a?(klass)) и Regexp (для действия, подобного =~, за исключением возврата логического значения). Некоторые классы, которые не определяют свои собственные ===, являются числовыми классами и String.

So

case x
when 0
  puts "Lots"
when Numeric
  puts(100.0 / x)
when /^\d+$/
  puts(100.0 / x.to_f)
default
  raise ArgumentError, "x is not a number or numeric string"
end

совпадает с

if 0 == x
  puts "Lots"
elsif x.is_a? Numeric
  puts(100.0 / x)
elsif x =~ /^\d+$/
  puts(100.0 / x.to_f)
else
  raise ArgumentError, "x is not a number or numeric string"
end
4 голосов
/ 22 января 2017

Интересный факт, === также используется для сопоставления исключений в rescue

Вот пример

class Example
  def self.===(exception)
    puts "Triple equals has been called."
    true
  end
end

raise rescue Example
# => prints "Triple equals has been called."
# => no exception raised

Это используется для сопоставления системных ошибок.

SystemCallError.=== был определен так, чтобы возвращать истину, когда оба имеют одинаковое значение errno.С помощью этого системного вызова можно устранить ошибки с одинаковым номером ошибки, такие как Errno::EAGAIN и Errno::EWOULDBLOCK, указав только одну из них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...