=== и == в Ruby


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

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

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

3 61

3 ответа:

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

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

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

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

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

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

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

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

case foo
when bar
  baz
end

это то же самое, что

if bar === foo
  baz
end

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

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

case obj
when x
  foo
when y
  bar
end

это то же самое, что

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

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

так

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

забавный факт, === также используется для сопоставления исключений в 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.=== было определено, чтобы вернуть true, когда два имеют одинаковый errno. При этом система вызывает ошибки с одинаковым номером ошибки, например Errno::EAGAIN и Errno::EWOULDBLOCK, оба могут быть спасены, перечисляя только один из них.