- 1. Факторіал
- 2. Строки
- 3. Регулярні вирази
А тепер давайте розберемо код із деяких наших попередніх прикладів програм.
Наступний приклад з'явився вперше в цьому розділі (https://evileg.com/ru/post/115/) .
def fact(n) if n == 0 1 else n * fact(n-1) end end print fact(ARGV[0].to_i), "\n"
Оскільки це перше пояснення, то розглянемо кожен рядок окремо.
Факторіал
def fact(n)
У першому рядку оператор def оголошує функцію (або, точніше, метод , ми поговоримо про методи в іншому розділі). Тут це вказує функцію fact, яка приймає один аргумент, описаний як n .
if n == 0
Далі перевірка умови. Коли умова виконується, тоді виконується код, наступний за умовою, інакше виконується код, що настає else .
1
Значення, що повертається, якщо умова виконалася.
else
Якщо умова не виконалася, то цей шматок коду виконується до оператора end.
n * fact(n-1)
Якщо умова не виконалося, то результатом є n якраз виконання функції факторіалу fact(n-1).
end
Перший оператор end, який закриває оператор if.
end
Другий оператор end, що закриває тіло функції, тобто оператор def .
print fact(ARGV[0].to_i), "\n"
Викликаємо функцію факторіалу fact() , використовуючи значення, передане в командний рядок і виводимо результат.
ARGV є масивом, який містить аргументи командного рядка. Елементи ARGV є рядками, тому ми повинні конвертувати їх у цілісний тип за допомогою методу *to_i. Ruby не перетворює рядки в цілісні типи автоматично, як це робить Perl.
Строки
Наступний приклад був показаний у розділі про рядки (https://evileg.com/ru/post/116/).
words = ['foobar', 'baz', 'quux'] secret = words[rand(3)] print "guess? " while guess = STDIN.gets guess.chop! if guess == secret print "you win\n" break else print "you lose.\n" end print "guess? " end print "the word is ", secret, ".\n"
У цій програмі є нова структура з умовою, це цикл while. Код між while та його відповідним оператором end буде виконуватися доти, доки виконується умова циклу.
rand(3) у рядку 2 повертає випадкове число в діапазоні від 0 до 2. Це випадкове число використовується для вилучення одного з трьох слів у масиві words .
У рядку 5 зчитується рядок зі стандартного введення STDIN.gets. Якщо отримано EOF (кінець файлу), gets повертає nil . Таким чином код повторюватиметься доти, доки не отримає комбінацію завершення D* (або * Z підDOS).
guess.chop! у рядку 6 видаляється останні символи зі змінної guess . У цьому випадку це завжди означає новий рядок.
У рядку 15 виводиться таємне слово. Ми маємо оператор print з трьома аргументами (які виводяться один за одним), але також ефективно, якби працювали з одним аргументом, записуючи secret як #{secret}, щоб було ясно, що це змінна, а не рядок для висновку:
print "the word is #{secret}.\n"
Регулярні вирази
І насамкінець розглянемо програму з розділу по регулярним виразам .
st = "\033[7m" en = "\033[m" while TRUE print "str> " STDOUT.flush str = gets break if not str str.chop! print "pat> " STDOUT.flush re = gets break if not re re.chop! str.gsub! re, "#{st}\\&#{en}" print str, "\n" end print "\n"
У рядку 4 умова циклу while встановлено в true. Таким чином зроблено нескінченний цикл. Однак у рядках 8 та 13 доданий оператор break для виходу з циклу. Ці два оператори break також є прикладом модифікації if . Модифікація if виконує оператор з лівого боку, лише якщо умова виконується.
Є кілька слів про метод chop! (див. рядки 9 та 14). У Ruby ми додаємо символи '!' або '?' наприкінці імен методів. Знак оклику (!, іноді вимовляється як "бах!") вказує на те, що метод є потенційно руйнівним і може змінити значення, якого стосується. chop! безпосередньо впливає на рядок, але просто chop без знака оклику працює як копіювання. У цьому полягає відмінність.
ruby> s1 = "forth" "forth" ruby> s1.chop! # This changes s1. "fort" ruby> s2 = s1.chop # This puts a changed copy in s2, "for" ruby> s1 # ... without disturbing s1. "fort"
Ви пізніше зіткнетеся з методом на кінці якого буде застосовуватись знак питання (?, Іноді вимовляється як "huh?"); який вказує що метод є предикатом, тобто повертає значення між true і false.
Рядок 15 заслуговує на пильну увагу. По-перше це метод gsub!, який є деструктивним методом. Він змінює змінну str, замінюючи всі символи, які збігаються з шаблоном re ( sub означає заміну, а символ g попереду означає глобальний вплив, тобто заміна всіх частин, що збіглися в рядку, а не тільки перший знайдений шматок ). Отже, все йде нормально, але що ми замінюємо у цьому тексті? st та en визначені в 1 та 2 рядках, як ANSI послідовності, які роблять текст нормальний та інвертований. У рядку 15 вони поміщені в #{} , щоб переконатися, що вони справді інтерпретуються як треба, а чи не як рядки висновку. Між ними бачимо послідовність "\&" . Це невеликий трюк. Так як заміна здійснюється в подвійних лапках, то пара зворотних слешів інтерпретуватиметься як "\&". В результаті буде надруковано новий рядок, схожий на старий, за винятком того, що будуть підсвічені ті частини, які збіглися з шаблоном.