Операторы равенства: == и! =
Оператор ==, также известный как равенство или двойное равенство, вернет true, если оба объекта равны, и false, если это не так.
"koan" == "koan" # Output: => true
Оператор! =, Также известный как неравенство, является противоположностью ==. Он вернет истину, если оба объекта не равны, и ложь, если они равны.
"koan" != "discursive thought" # Output: => true
Обратите внимание, что два массива с одинаковыми элементами в разном порядке не равны, прописные и строчные версии одной и той же буквы не равны и так далее.
При сравнении чисел разных типов (например, целых и чисел с плавающей точкой), если их числовые значения одинаковы, == вернет true.
2 == 2.0 # Output: => true
равны?
В отличие от оператора ==, который проверяет, равны ли оба операнда, метод равенства проверяет, ссылаются ли два операнда на один и тот же объект. Это самая строгая форма равенства в Ruby.
Пример: a = "zen" b = "zen"
a.object_id # Output: => 20139460
b.object_id # Output :=> 19972120
a.equal? b # Output: => false
В приведенном выше примере у нас есть две строки с одинаковым значением. Однако это два разных объекта с разными идентификаторами объектов. Значит, равный? метод вернет false.
Попробуем еще раз, только на этот раз b будет ссылкой на a. Обратите внимание, что идентификатор объекта одинаков для обеих переменных, так как они указывают на один и тот же объект.
a = "zen"
b = a
a.object_id # Output: => 18637360
b.object_id # Output: => 18637360
a.equal? b # Output: => true
EQL?
В классе Hash, eql? Метод используется для проверки ключей на равенство. Некоторый фон требуется, чтобы объяснить это. В общем контексте вычислений хеш-функция берет строку (или файл) любого размера и генерирует строку или целое число фиксированного размера, называемое хеш-кодом, обычно называемое только хеш-кодом. Некоторые часто используемые типы хеш-кодов: MD5, SHA-1 и CRC. Они используются в алгоритмах шифрования, индексации базы данных, проверке целостности файлов и т. Д. Некоторые языки программирования, такие как Ruby, предоставляют тип коллекции, называемый хэш-таблицей. Хеш-таблицы - это словарные коллекции, в которых данные хранятся парами, состоящими из уникальных ключей и соответствующих им значений. Под капотом эти ключи хранятся в виде хэш-кодов. Хеш-таблицы обычно называют просто хешами. Обратите внимание, как слово hash может относиться к хеш-коду или хеш-таблице.
Ruby предоставляет встроенный метод hash для генерации хеш-кодов. В приведенном ниже примере он принимает строку и возвращает хеш-код. Обратите внимание, что строки с одинаковым значением всегда имеют одинаковый хеш-код, даже если они являются разными объектами (с разными идентификаторами объектов).
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
Хеш-метод реализован в модуле Kernel, включенном в класс Object, который является корнем по умолчанию для всех объектов Ruby. Некоторые классы, такие как Symbol и Integer, используют реализацию по умолчанию, другие, такие как String и Hash, предоставляют свои собственные реализации.
Symbol.instance_method(:hash).owner # Output: => Kernel
Integer.instance_method(:hash).owner # Output: => Kernel
String.instance_method(:hash).owner # Output: => String
Hash.instance_method(:hash).owner # Output: => Hash
В Ruby, когда мы храним что-то в хеше (коллекции), объект, предоставленный как ключ (например, строка или символ), преобразуется в и сохраняется как хеш-код. Позже, извлекая элемент из хеша (коллекции), мы предоставляем объект в качестве ключа, который преобразуется в хеш-код и сравнивается с существующими ключами. Если есть совпадение, возвращается значение соответствующего элемента. Сравнение сделано с помощью EQL? метод под капотом.
"zen".eql? "zen" # Output: => true
# is the same as
"zen".hash == "zen".hash # Output: => true
В большинстве случаев, eql? Метод ведет себя аналогично методу ==. Однако есть несколько исключений. Например, eql? не выполняет неявное преобразование типов при сравнении целого числа с плавающей точкой.
2 == 2.0 # Output: => true
2.eql? 2.0 # Output: => false
2.hash == 2.0.hash # Output: => false
Оператор равенства случая: ===
Многие встроенные в Ruby классы, такие как String, Range и Regexp, предоставляют свои собственные реализации оператора ===, также известного как case-равенства, тройного равенства или тройного равенства. Поскольку он реализован по-разному в каждом классе, он будет вести себя по-разному в зависимости от типа объекта, к которому он был вызван. Как правило, он возвращает true, если объект справа «принадлежит» или «является членом» объекта слева. Например, его можно использовать для проверки того, является ли объект экземпляром класса (или одним из его подклассов).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
Тот же результат может быть достигнут с помощью других методов, которые, вероятно, лучше всего подходят для работы. Как правило, лучше писать код, который легко читать, будучи максимально явным, не жертвуя эффективностью и краткостью.
2.is_a? Integer # Output: => true
2.kind_of? Integer # Output: => true
2.instance_of? Integer # Output: => false
Обратите внимание, что последний пример вернул false, поскольку целые числа, такие как 2, являются экземплярами класса Fixnum, который является подклассом класса Integer. ===, is_a? и instance_of? методы возвращают true, если объект является экземпляром данного класса или любых подклассов. Метод instance_of является более строгим и возвращает true, только если объект является экземпляром этого точного класса, а не подклассом.
Is_a? и добрый_? методы реализованы в модуле Kernel, который смешивается с классом Object. Оба являются псевдонимами одного и того же метода. Давайте проверим:
Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Выход: => true
Диапазон реализации ===
Когда оператор === вызывается для объекта диапазона, он возвращает true, если значение справа попадает в диапазон слева.
(1..4) === 3 # Output: => true
(1..4) === 2.345 # Output: => true
(1..4) === 6 # Output: => false
("a".."d") === "c" # Output: => true
("a".."d") === "e" # Output: => false
Помните, что оператор === вызывает метод === левого объекта. Итак, (1..4) === 3 эквивалентно (1..4). === 3. Другими словами, класс левого операнда определит, какая реализация метода === будет называется, так что позиции операндов не являются взаимозаменяемыми.
Regexp Реализация ===
Возвращает true, если строка справа соответствует регулярному выражению слева. / zen / === "тренируйся дзадзэн сегодня" # Вывод: => true # - то же самое, что и "тренируйся дзадзэн сегодня" = ~ / zen /
Неявное использование оператора === в операторах case / when
Этот оператор также используется под оператором case / when. Это его наиболее распространенное использование.
minutes = 15
case minutes
when 10..20
puts "match"
else
puts "no match"
end
# Output: match
В приведенном выше примере, если в Ruby неявно использовался оператор двойного равенства (==), диапазон 10..20 не будет считаться равным целому числу, например 15. Они совпадают, поскольку оператор тройного равенства (===) неявно используется во всех случаях / когда заявления. Код в приведенном выше примере эквивалентен:
if (10..20) === minutes
puts "match"
else
puts "no match"
end
Операторы сопоставления с образцом: = ~ и! ~
Операторы = ~ (equal-tilde) и! ~ (Bang-tilde) используются для сопоставления строк и символов с шаблонами регулярных выражений.
Реализация метода = ~ в классах String и Symbol предполагает регулярное выражение (экземпляр класса Regexp) в качестве аргумента.
"practice zazen" =~ /zen/ # Output: => 11
"practice zazen" =~ /discursive thought/ # Output: => nil
:zazen =~ /zen/ # Output: => 2
:zazen =~ /discursive thought/ # Output: => nil
Реализация в классе Regexp ожидает строку или символ в качестве аргумента.
/zen/ =~ "practice zazen" # Output: => 11
/zen/ =~ "discursive thought" # Output: => nil
Во всех реализациях, когда строка или символ соответствуют шаблону Regexp, он возвращает целое число, которое является позицией (индексом) соответствия. Если совпадений нет, возвращается ноль. Помните, что в Ruby любое целочисленное значение является «правдивым», а nil - «ложным», поэтому оператор = ~ можно использовать в операторах if и троичных операторах.
puts "yes" if "zazen" =~ /zen/ # Output: => yes
"zazen" =~ /zen/?"yes":"no" # Output: => yes
Операторы сопоставления с образцом также полезны для написания более коротких операторов if. Пример:
if meditation_type == "zazen" || meditation_type == "shikantaza" || meditation_type == "kinhin"
true
end
Can be rewritten as:
if meditation_type =~ /^(zazen|shikantaza|kinhin)$/
true
end
Оператор! ~ Противоположен = ~, он возвращает истину, если совпадения нет, и ложь, если совпадение есть.
Более подробная информация доступна в этом блоге .
"a" == "a"
,"a" === "a"
и"a".eql? "a"
. Но это неверно:"a".equal? "a"
(Мой - ruby 1.9.2-p180)