В уроці про основні концепції програмування вже частково торкалися цієї теми, але я б хотів ще показати вам про існування тернарного оператора та як його використовувати, а також розглянемо керуючу структуру case.
Отже, давайте нагадаємо собі як виглядає класична керуюча структура if else:
Він займає аж 5 рядків, хоча сенс його тривіальний.
За допомогою теранрного оператора попередній приклад буде виглядати так:
Або навіть ще лаконічніше:
Ось як це потрібно розуміти:
умова ? якщо_true : якщо_false
І ще один приклад для закріплення:
Пріоритет
У тернарного оператора в ruby один з найнижчих пріоритетів , нижче - тільки в операцій присвоєння, конструкцій, що керують, блоків і т.д.
Про це важливо пам'ятати, коли його використовуєте в таких випадках:
Ви отримаєте помилку: «in `+': no implicit conversion of true into String (TypeError)».
Щоб уникнути даної ситуації використовуйте дужки:
Кожного разу, коли вам потрібно використати оператори if / elsif, ви можете розглянути можливість використання оператора case. Розглянемо декілька різних випадків використання та про те, як усе це насправді працює під капотом.
Оператор case більш гнучкий, ніж може здатися на перший погляд. Давайте подивимося приклад, коли ми хочемо надрукувати деяке повідомлення залежно від того, до якого діапазону потрапляє значення.
Я думаю, що цей код досить елегантний порівняно з тим, як виглядала б версія if / elsif.
Крім того можна перераховувати через кому декілька умов після when:
Ви також можете використовувати регулярні вирази як умову when. У наступному прикладі ми маємо serial_code з початковою літерою, яка повідомляє нам, наскільки ризиковано споживати цей продукт.
Коли у вас є просте відображення 1:1, у вас може виникнути спокуса зробити щось подібне.
На мою думку, краще це зробити наступним чином:
Хеш-рішення є ефективнішим і з ним легше працювати. А як ви вважаєте?
Вам може бути цікаво, як case працює під капотом. Якщо ми повернемося до нашого першого прикладу, ось що відбувається:
=== — це просто метод, який може бути реалізований будь-яким класом. У цьому випадку Range реалізує цей метод, повертаючи true, лише якщо значення знайдено всередині діапазону.
Ось як метод === реалізовано в Rubinius (для класу Range):
Іншим цікавим класом, який реалізує ===, є клас Proc. В наступному уроці ми детальніше поговоримо про Proc, а на разі наведу приклад поєднання Procs та Case.
У цьому прикладі я визначаю два procs (процедури), одну для перевірки парного числа (even), а іншу для непарних (odd).
Ось що насправді відбувається:
Використання === у процедурі має той самий ефект, що й використання call.
Ви дізналися, як працює оператор case в Ruby і наскільки він може бути гнучким. А коли використовувати case, а коли if else – ви зрозумієте під час практики з досвідом.
Цикл (loop) дозволяє повторювати дію багато разів.
Це дозволяє:
Почнемо з найважливіших методів циклу в Ruby послідовно.
Метод each дозволяє вам переглядати список елементів, не відстежуючи кількість ітерацій або збільшуючи якийсь лічильник.Це спосіб в Ruby: «повторювати, поки не буде зроблено».
Метод each використовується на колекції масивів, діапазонів та хешів.
Приклад:
Простою українською мовою це означає:
«Для кожного елемента цифрами виведіть його значення».
Ви вказуєте кожному методу (в даному випадку puts), що робити з кожним елементом, використовуючи блок.
У цьому прикладі все після each є блоком:
Що ж тут відбувається? Так це те, що each використовуватиме блок один раз для кожного елемента в масиві та передаватиме в нього кожен окремий елемент, тому n є змінною.
Пам'ятайте:
Метою циклу є повторення або «перебирання» ВСІХ елементів зі списку, цей список може приймати різні форми, але зазвичай це масив.
Існують різні способи зробити це залежно від ситуації.
Найпоширенішим є використання методу each, оскільки вам не потрібно відстежувати поточну позицію в списку.
Якщо ви хочете використовувати метод each із хешем, вам знадобляться два параметри: один для ключа, інший для значення.
Решта синтаксису така ж, і вам все одно потрібен блок.
Приклад:
Спробуйте відтворити це в себе локально!
Якщо ви хочете використовувати each і вам потрібен номер індексу елементу, то ви можете використовувати метод each_with_index:
Це дозволяє циклічно перебирати масив, маючи доступ до поточного індексу.
Пам'ятайте, що індекс починається з 0.
Це найпростіший цикл, з яким ви можете працювати.
Просто подивіться на цей код:
Досить простий метод як не тяжко запам’ятати та зрозуміти як з ним працювати. Але що, якщо вам потрібен номер кожної поточної ітерації?
В останньому прикладі з циклом each ми мали доступ змінної n, щоб ми могли її надрукувати. Ви також можете зробити це з методом times.
Приклад:
Ключовим тут є маленьке |i| річ, яка, може бути будь-якою допустимою назвою зміни. Це не обов’язково має бути |i|. Це може бути |n| або |foo|, або |becon|… Це просто назва!
Якщо ви знайомі з методами, це |n| це як параметр методу.
Іншими словами, це просто змінна, яка стає поточним значенням для кожної ітерації нашого циклу times.
Можливо, ви помітили, що під час використання методу times він починає відлік від 0. Це може бути трохи незручно, якщо ви хочете почати з іншого числа. Ви можете використовувати діапазон і метод times, щоб краще контролювати початкові та кінцеві числа.
Приклад:
Цикл while доступний у більшості мов програмування, тому його завжди корисно знати. Це також тип циклу, до якого ви можете повернутися, коли все інше не вдається. while виконує код (тіло циклу), поки справджується умова. І бувають ситуації, коли лише цикл while мав би сенс. Наприклад, якщо ви не знаєте, скільки разів вам потрібно повторити ітерацію заздалегідь.
Приклад:
Зверніть увагу, що є кілька важливих компонентів:
Усі ці компоненти є важливими для роботи.
Змінна n містить значення, яке ми використовуємо для підрахунку, умова (n < 10) повідомляє Ruby, коли зупинити цей цикл (коли значення n більше або дорівнює 10), а n += 1 збільшує лічильник на +1 за ітерацію, щоб рано чи пізно виконати умову.
Якщо ви «забудете» збільшувати лічильник у циклі while, ви зіткнетеся з програмою, яка ніколи не закінчиться - нескінченна петля!
Але будь-який поважаючий себе програміст, хоч раз зробить це, have fun 😊
Як я б не намагався сформулювати приклад на українській мові на словах, щоб передати зміст - мені не виходить, тому буде на англійській.
Існує ще одне ключове слово, until, воно робить те саме, що й while, але умова зворотна.
Якщо ви хочете повторювати, поки пляшка не заповниться, ви можете сказати:
«Do something WHILE the bottle is NOT full»
У ruby є негативні твердження, які ми намагаємося уникати, оскільки вони ускладнюють розуміння логіки.
«Do something UNTIL the bottle IS full»
Варіант з until набагато природніше читати та розуміти.
Отже, until буде виконуватися доки умова є хибною (false)
А while навпаки - поки умова є істинною (true)
Ви можете пропускати ітерації в усіх цих типах циклу.
Інші мови використовують оператор continue, а у Ruby ми використовуємо ключове слово next.
Скажімо, ви переглядаєте масив чисел і хочете пропустити непарні числа.
Тоді ми можемо зробити наступне:
Основним тут є ключове слово next, яке переходить до наступної ітерації циклу, якщо змінна i є непарним числом
Кращий спосіб зробити це — скористатися іншими методами, наприклад step & select.
Приклад:
Звернуть увагу як нам повертаються дані з цих методів
Ви також можете вийти з циклу раніше, до того, як умова буде виконана, або до того, як ви переглянете всі елементи колекції.
Наступний приклад зупиняється, коли знаходить число більше 10
Ключовим тут є ключове слово break. Коли ви використовуєте break, ви негайно завершуєте цикл, тому майте це на увазі.
Це також працює для циклів while.
Якщо це ще не зрозуміло, Ruby дуже гнучкий, ось ще один метод для створення циклу.
Метод upto.
Ви дізналися багато різних способів циклу в Ruby!
Включаючи метод times, метод each і ключове слово while.
Ви також побачили як керувати циклами, пропускаючи ітерації за допомогою next і виходячи з циклів за допомогою break.
З усіма цими методами вам НІКОЛИ не доведеться використовувати цикл for, який є марним залишком інших мов.
Якщо ви хочете написати код, схожий на Ruby (те, що ми називаємо «ідіоматичним кодом»), використовуйте методи циклу, які ви навчилися в цьому посібнику.
P.S. ідіоматичний код Ruby – це грубо кажучи, в якому стилі буде виглядати ваш код. Ви можете написати код Ruby, але він може виглядати, наприклад, як код Java –
Починаючи з цього уроку, наполегливо рекомендую практикуватися і пробувати все, що пройшли на уроці.
ДЗ? А чому б ні? Будемо рахувати «рубіни»!
Розгляньте масив «рубінів», де деякі «рубіни» можуть бути відсутні на своєму місці. Нам потрібний метод, який підрахує кількість «рубінів» у масиві (true означає наявність).
Підготував вам заготовку, але її не обов’язково використовувати(окрім вхідних даних). Хто зможе вирішити – діліться в чаті, буде цікаво подивитися в кого який підхід 😊
Трохи офіційної документації:
Методи:
Ключові слова while та until та цикли загалом.
Завантажити сьогоднішній матеріал файлом можна тут.
Група в телеграмі: https://t.me/ruby4you
Автор курсу: Шкоропад Даниїл