Оператори рівності: == і! =
Оператор ==, також відомий як рівність або подвійне рівне, поверне істину, якщо обидва об'єкти рівні та помилкові, якщо їх немає.
"koan" == "koan" # Output: => true
Оператор! =, Також відомий як нерівність, протилежний ==. Він повернеться істинним, якщо обидва об'єкти не рівні і хибні, якщо вони рівні.
"koan" != "discursive thought" # Output: => true
Зауважте, що два масиви з однаковими елементами в різному порядку не рівні, великі та малі версії однієї і тієї ж літери не рівні і так далі.
Якщо порівнювати числа різних типів (наприклад, цілих чи плаваючих), якщо їх числове значення однакове, == повернеться істинним.
2 == 2.0 # Output: => true
рівний?
На відміну від оператора ==, який перевіряє, чи обидва операнди рівні, однаковий метод перевіряє, чи обидва операнди відносяться до одного об'єкта. Це найсуворіша форма рівності у Рубі.
Приклад: a = "zen" b = "zen"
a.object_id # Output: => 20139460
b.object_id # Output :=> 19972120
a.equal? b # Output: => false
У наведеному вище прикладі маємо дві струни з однаковим значенням. Однак вони є двома різними об'єктами, з різними ідентифікаторами об'єктів. Значить, рівне? метод поверне помилковий.
Спробуємо ще раз, лише цього разу b буде посиланням на a. Зауважте, що ідентифікатор об'єкта однаковий для обох змінних, оскільки вони вказують на один і той же об'єкт.
a = "zen"
b = a
a.object_id # Output: => 18637360
b.object_id # Output: => 18637360
a.equal? b # Output: => true
екв?
У класі Hash, eql? метод використовується для тестування ключів на рівність. Для пояснення цього потрібно деякий досвід. У загальному контексті обчислень хеш-функція приймає рядок (або файл) будь-якого розміру і генерує рядок або ціле число фіксованого розміру, що називається хеш-кодом, зазвичай називають тільки хеш. Деякі типи хеш-кодів, які часто використовуються, - це MD5, SHA-1 та CRC. Вони використовуються в алгоритмах шифрування, індексації баз даних, перевірки цілісності файлів тощо. Деякі мови програмування, такі як Ruby, надають тип колекції, що називається хеш-таблицею. Хеш-таблиці - це схожі словники, які зберігають дані в парах, що складаються з унікальних ключів та відповідних їм значень. Під капотом ці ключі зберігаються як хеш-коди. Таблиці хешу зазвичай називають хешами. Зверніть увагу, як слово хешкан посилається на хеш-код або хеш-таблицю.
Ruby пропонує вбудований метод під назвою хеш для генерування хеш-кодів. У наведеному нижче прикладі він бере рядок і повертає хеш-код. Зауважте, як рядки з однаковим значенням завжди мають однаковий хеш-код, навіть якщо вони є різними об'єктами (з різними ідентифікаторами об'єктів).
"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? не виконує неявне перетворення типу при порівнянні цілого числа з плаваючою.
2 == 2.0 # Output: => true
2.eql? 2.0 # Output: => false
2.hash == 2.0.hash # Output: => false
Оператор рівності випадків: ===
Багато вбудованих класів Ruby, такі як String, Range та Regexp, забезпечують власні реалізації оператора ===, також відомий як рівність випадків, потрійне рівне або трирівневе значення. Оскільки він реалізується по-різному в кожному класі, він буде поводитися по-різному в залежності від типу об'єкта, на який він був викликаний. Як правило, він повертає істину, якщо об’єкт праворуч "належить" або "є членом" об'єкта зліва. Наприклад, з його допомогою можна перевірити, чи об’єкт є екземпляром класу (або одним із його підкласів).
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
Зауважте, що останній приклад повернув помилкове значення, оскільки цілі числа, такі як 2, є екземплярами класу Fixnum, який є підкласом класу Integer. ===, is_a? і instance_of? методи повертають істину, якщо об'єкт є примірником даного класу або будь-якими підкласами. Метод instance_of є більш суворим і повертає true лише в тому випадку, якщо об'єкт є екземпляром цього точного класу, а не підкласом.
Is_a? і kind_of? методи реалізовані в модулі Kernel, який змішується класом Object. Обидва є псевдонімами одного і того ж методу. Давайте перевіримо:
Kernel.instan_method (: kind_of?) == Kernel.instan_method (: is_a?) # Вихід: => 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
Цей оператор також використовується під кришкою на випадок / коли. Це найпоширеніше його використання.
minutes = 15
case minutes
when 10..20
puts "match"
else
puts "no match"
end
# Output: match
У наведеному вище прикладі, якби Рубі неявно використав оператор подвійного рівного (==), діапазон 10..20 не вважався б рівним цілому числу, таким як 15. Вони відповідають тому, що потрійний оператор (===) є неявно використовується у всіх випадках / коли твердженнях. Код у наведеному вище прикладі еквівалентний:
if (10..20) === minutes
puts "match"
else
puts "no match"
end
Оператори відповідності шаблонів: = ~ і! ~
Оператори = ~ (equi-tilde) і! ~ (Bang-tilde) використовуються для зіставлення рядків і символів з шаблонами регулярних виразів.
Реалізація методу = ~ у класах String and 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 будь-яке ціле значення є "truthy", а nil - "falsy", тому оператор = ~ може використовуватися в операторах, якщо оператори та потрійні оператори.
puts "yes" if "zazen" =~ /zen/ # Output: => yes
"zazen" =~ /zen/?"yes":"no" # Output: => yes
Оператори відповідності шаблонів також корисні для написання коротших, якщо висловлювань. Приклад:
if meditation_type == "zazen" || meditation_type == "shikantaza" || meditation_type == "kinhin"
true
end
Can be rewritten as:
if meditation_type =~ /^(zazen|shikantaza|kinhin)$/
true
end
Оператор! ~ Протилежний = ~, він повертає true, коли немає відповідності, і false, якщо є збіг.
Більше інформації можна отримати у цій публікації в блозі .
"a" == "a"
,"a" === "a"
і"a".eql? "a"
. Але це помилково:"a".equal? "a"
(Mine is ruby 1.9.2-p180)