mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 17:41:41 +00:00
19 KiB
19 KiB
language | filename | contributors | translators | lang | ||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Ruby | learnruby-ua.rb |
|
|
uk-ua |
Rubi — це інтерпретована, повністю об'єктно-орієнтована мова програмування з чіткою динамічною типізацією.
# Це коментар
=begin
Це багаторядковий коментар
Ніхто їх не використовує
Тобі теж не варто
=end
# В першу чергу: все являється об’єктом.
# Числа це об’єкти
3.class #=> Fixnum
3.to_s #=> "3"
# Базова арифметика
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
2**5 #=> 32
5 % 3 #=> 2
# Побітові оператори
3 & 5 #=> 1
3 | 5 #=> 7
3 ^ 5 #=> 6
# Арифметика це просто синтаксичний цукор
# для виклику методу об’єкта
1.+(3) #=> 4
10.* 5 #=> 50
# Спеціальні значення теж об’єкти
nil # еквівалентно null в інших мовах
true # істина
false # хиба
nil.class #=> NilClass
true.class #=> TrueClass
false.class #=> FalseClass
# Рівність
1 == 1 #=> true
2 == 1 #=> false
# Нерівність
1 != 1 #=> false
2 != 1 #=> true
# Окрім власне false, nil це ще одне "хибне" значення
!nil #=> true
!false #=> true
!0 #=> false
# Інші порівняння
1 < 10 #=> true
1 > 10 #=> false
2 <= 2 #=> true
2 >= 2 #=> true
# Комбінований оператор порівняння
1 <=> 10 #=> -1
10 <=> 1 #=> 1
1 <=> 1 #=> 0
# Логічні оператори
true && false #=> false
true || false #=> true
!true #=> false
# Є альтернативні версії логічних операторів з набагато меншим
# прецедентом. Вони використовуються в конструкціях з контролем
# виконання ланцюга виразів які повертають булевий результат.
# `do_something_else` викликається лише якщо `do_something` повертає true.
do_something() and do_something_else()
# `log_error` викликається лише якщо `do_something` повертає false.
do_something() or log_error()
# Strings це об’єкти
'Я — рядок'.class #=> String
"Я теж рядок".class #=> String
placeholder = 'використовувати інтерполяцію рядків'
"Я можу #{placeholder} коли користуюсь рядками в подвійних лапках"
#=> "Я можу використовувати інтерполяцію рядків коли користуюсь рядками в подвійних лапках"
# Варто надавати перевагу рядкам в одинарних лапках де це можливо
# Рядки в подвійних лапках викликають додаткові внутрішні обчислення
# Об’єднуйте рядки, але не з числами
'hello ' + 'world' #=> "hello world"
'hello ' + 3 #=> TypeError: can't convert Fixnum into String
'hello ' + 3.to_s #=> "hello 3"
# Об’єднуйте рядки з операторами
'hello ' * 3 #=> "hello hello hello "
# Додавання до рядка
'hello' << ' world' #=> "hello world"
# Вивести рядок з переходом на новий рядок вкінці
puts "Я надрукований!"
#=> Я надрукований!
#=> nil
# Вивести рядок без переходу на новий
print "Я надрукований!"
#=> Я надрукований! => nil
# Змінні
x = 25 #=> 25
x #=> 25
# Зверніть увагу, оператор присвоєння повертає присвоєне значення
# Отже можна робити одночасне присвоєння кількох змінних:
x = y = 10 #=> 10
x #=> 10
y #=> 10
# Для назв змінних використовується зміїний_регістр
snake_case = true
# Використовуйте назви змінних які їх характеризують
path_to_project_root = '/good/name/'
path = '/bad/name/'
# Символи (теж об’єкти)
# Символи є незмінними константами багаторазового використання, внутрішньо
# представлені цілочисельним значенням. Вони часто використовуються замість
# рядків щоб ефективно передати конкретні, значущі значення.
:pending.class #=> Symbol
status = :pending
status == :pending #=> true
status == 'pending' #=> false
status == :approved #=> false
# Масиви
# Ось масив
array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
# Масиви можуть містити елементи різних типів
[1, 'hello', false] #=> [1, "hello", false]
# Масиви можуть бути проіндексовані
# З початку
array[0] #=> 1
array.first #=> 1
array[12] #=> nil
# Як і арифметика, доступ до елемента масиву у вигляді [індекс] — це лише
# синтаксичний цукор виклику методу [] об’єкта
array.[] 0 #=> 1
array.[] 12 #=> nil
# З кінця
array[-1] #=> 5
array.last #=> 5
# З початковим індексом та довжиною
array[2, 3] #=> [3, 4, 5]
# Реверс масиву
a=[1,2,3]
a.reverse! #=> [3,2,1]
# Елементи масиву за діапазоном індексів
array[1..3] #=> [2, 3, 4]
# Додавати елементи в масив можна так:
array << 6 #=> [1, 2, 3, 4, 5, 6]
# Або так:
array.push(6) #=> [1, 2, 3, 4, 5, 6]
# Перевірити чи масив містить елемент
array.include?(1) #=> true
# Хеш — це масив пар ключ/значення.
# Хеш оголошується з використанням фігурних дужок:
hash = { 'color' => 'green', 'number' => 5 }
hash.keys #=> ['color', 'number']
# Значення в хеші може бути швидко знайдене за ключем:
hash['color'] #=> 'green'
hash['number'] #=> 5
# Запит значення за неіснуючим ключем повертає nil:
hash['nothing here'] #=> nil
# Починаючи з Ruby 1.9 з’явився спеціальний синтаксис при використанні
# символів в якості ключів:
new_hash = { defcon: 3, action: true }
new_hash.keys #=> [:defcon, :action]
# Перевірка наявності ключів та значень в хеші
new_hash.key?(:defcon) #=> true
new_hash.value?(3) #=> true
# Хеші та масиви — перелічувальні типи даних
# Вони мають багато корисних методів, такі як each, map, count, та інші.
# Оператор вибору "if"
if true
'якщо'
elsif false
'інакше якщо, опціонально'
else
'інакше, також опціонально'
end
# Оператор циклу "for"
for counter in 1..5
puts "ітерація #{counter}"
end
#=> ітерація 1
#=> ітерація 2
#=> ітерація 3
#=> ітерація 4
#=> ітерація 5
# Проте, ніхто не використовує "for" в циклах.
# Замість цього варто використовувати метод "each" і передати йому блок.
# Блок — це відокремлений код який можна передати в метод, наприклад в "each".
# Це аналог лямбда-виразів, анонімних функцій або замикань в інших мовах програмування.
# Метод "each" для діапазону запускає блок один раз для кожного елементу діапазону.
# Лічильник передається блоку в якості аргументу.
# Виклик методу "each" з блоком виглядає наступним чином:
(1..5).each do |counter|
puts "ітерація #{counter}"
end
#=> ітерація 1
#=> ітерація 2
#=> ітерація 3
#=> ітерація 4
#=> ітерація 5
# Також можна загорнути блок в фігурні дужки:
(1..5).each { |counter| puts "ітерація #{counter}" }
# Вміст структур даних також може бути ітерований використовуючи метод "each":
array.each do |element|
puts "#{element} є елементом масиву"
end
hash.each do |key, value|
puts "#{key} є #{value}"
end
# Якщо є необхідність індексувати ітерацію, можна використати метод "each_with_index":
array.each_with_index do |element, index|
puts "#{element} під номером #{index} в масиві"
end
# Оператор циклу "while"
counter = 1
while counter <= 5 do
puts "ітерація #{counter}"
counter += 1
end
#=> ітерація 1
#=> ітерація 2
#=> ітерація 3
#=> ітерація 4
#=> ітерація 5
# Є й інші корисні функції для циклів, такі як "map", "reduce",
# "inject" та інші. Наприклад "map" в циклі проходить по масиву,
# виконує над елементами операцію(-ї) в блоці і повертає абсолютно
# новий масив.
array = [1,2,3,4,5]
doubled = array.map do |element|
element * 2
end
puts doubled
#=> [2,4,6,8,10]
puts array
#=> [1,2,3,4,5]
# Оператор множинного вибору
grade = 'B'
case grade
when 'A'
puts 'Відмінно!'
when 'B'
puts 'Пощастить наступного разу'
when 'C'
puts 'Ти можеш краще'
when 'D'
puts 'Майже четвірка'
when 'E'
puts 'Випросив'
when 'F'
puts 'Не здав!'
else
puts 'Інша система оцінювання, так?'
end
#=> "Пощастить наступного разу"
# Оператор "case" також може використовувати діапазон:
grade = 82
case grade
when 90..100
puts 'Ура!'
when 80...90
puts 'Хороша робота'
when 60...80
puts 'Ну, хоч щось'
else
puts 'Не здав!'
end
#=> "Хороша робота"
# Обробка вийнятків:
begin
# код з можливим вийнятком
raise NoMemoryError, 'Ви використали всю пам’ять.'
rescue NoMemoryError => exception_variable
puts 'Помилка NoMemoryError', exception_variable
rescue RuntimeError => other_exception_variable
puts 'Помилка RuntimeError'
else
puts 'Цей код запуститься якщо вийнятків не було взагалі'
ensure
puts 'Цей код запуститься в будь-якому випадку'
end
# Функції
def double(x)
x * 2
end
# Функції (і всі блоки) неявно повертають значення останнього виразу
double(2) #=> 4
# Дужки не є обов’язковими якщо результат недвозначний
double 3 #=> 6
double double 3 #=> 12
def sum(x, y)
x + y
end
# Аргументи методів розділяються комою
sum 3, 4 #=> 7
sum sum(3, 4), 5 #=> 12
# yield
# Всі методи мають неявний, опціональний параметр, який
# можна викликат за допомогою ключового слова 'yield'
def surround
puts '{'
yield
puts '}'
end
surround { puts 'привіт світ' }
# {
# привіт світ
# }
# Ви можете передати блок у функцію
# "&" позначає посилання на блок
def guests(&block)
block.call 'some_argument'
end
# Ви можете передати список аргументів, вони будуть перетворені в масив
# Для цього існує оператор ("*")
def guests(*array)
array.each { |guest| puts guest }
end
# Якщо метод повертає масив, ви можете використати деструктуризацію
def foods
['млинці', 'бутерброд', 'лазанья']
end
breakfast, lunch, dinner = foods
breakfast #=> 'млинці'
dinner #=> 'лазанья'
# Зазвичай методи які повертають булевий результат закінчуються знаком питання
5.even? # false
5.odd? # true
# І якщо метод закінчується знаком оклику, то він робить щось деструктивне
# типу зміни отриманого аргументу. Багато методів мають версію з "!" які
# змінюють аргумент, та без "!" що повертають новий об’єкт
company_name = "Дандер Міфлін"
company_name.upcase #=> "ДАНДЕР МІФЛІН"
company_name #=> "Дандер Міфлін"
company_name.upcase! # змінна company_name зміниться цього разу!
company_name #=> "ДАНДЕР МІФЛІН"
# Клас оголошується ключовим словом class
class Human
# Змінна класу. Вона поширюється на всі екземпляри цього класу.
@@species = 'Homo sapiens'
# Основний ініціалізатор
def initialize(name, age = 0)
# Призначення аргументу "name" до однойменної змінної екземпляру
@name = name
# Якщо аргумент "age" не заданий, то йому буде присвоєно дефолтне значення
# зі списку аргументів
@age = age
end
# Метод-сетер
def name=(name)
@name = name
end
# Метод-ґетер
def name
@name
end
# Функціональність вище може бути інкапсульована використовуючи метод attr_accessor:
attr_accessor :name
# Ґетери і сетери можуть бути створені індивідуально, наприклад:
attr_reader :name
attr_writer :name
# Метод класу позначається ключовим словом "self", щоб відрізнити від
# методів екземпляра класу.
# Він може бути викликаний лише в класі, але не в екземплярі.
def self.say(msg)
puts msg
end
def species
@@species
end
end
# Ініціалізуємо клас
jim = Human.new('Джим Галперт')
dwight = Human.new('Дуайт Шрут')
# Викличемо кілька методів
jim.species #=> "Homo sapiens"
jim.name #=> "Джим Галперт"
jim.name = "Джим Галперт II" #=> "Джим Галперт II"
jim.name #=> "Джим Галперт II"
dwight.species #=> "Homo sapiens"
dwight.name #=> "Дуайт Шрут"
# Викликати метод класу
Human.say('Привіт') #=> "Привіт"
# Область видимості змінних визначається способом оголошення імені змінної.
# Змінні, що починаються на "$" мають глобальну область видимості.
$var = "Я глобальна змінна"
defined? $var #=> "global-variable"
# Зміннні, що опчинають на "@" мають область видимості екзкмпляра
@var = "Я змінна екземпляра"
defined? @var #=> "instance-variable"
# Змінні, що починаються на "@@" мають область видимості класу
@@var = "Я змінна класу"
defined? @@var #=> "class variable"
# Змінні, що починаються з великої букви, є константами
Var = "Я константа"
defined? Var #=> "constant"
# Клас теж об’єкт. Тому клас може мати змінні екземпляра.
# Змінна класу поширюється між класом і всіма його нащадками.
# Базовий клас
class Human
@@foo = 0
def self.foo
@@foo
end
def self.foo=(value)
@@foo = value
end
end
# Похідний клас (нащадок)
class Worker < Human
end
Human.foo # 0
Worker.foo # 0
Human.foo = 2 # 2
Worker.foo # 2
# Змінна екземпляра класу не поширюється між класами-нащадками.
class Human
@bar = 0
def self.bar
@bar
end
def self.bar=(value)
@bar = value
end
end
class Doctor < Human
end
Human.bar # 0
Doctor.bar # nil
module ModuleExample
def foo
'foo'
end
end
# Включення модулів додає їхні методи до екземплярів класу
# Розширення модулів додає їхні методи в сам клас
class Person
include ModuleExample
end
class Book
extend ModuleExample
end
Person.foo # => NoMethodError: undefined method `foo' for Person:Class
Person.new.foo # => 'foo'
Book.foo # => 'foo'
Book.new.foo # => NoMethodError: undefined method `foo'
# Колбек виконується при включенні і розширенні модуля
module ConcernExample
def self.included(base)
base.extend(ClassMethods)
base.send(:include, InstanceMethods)
end
module ClassMethods
def bar
'bar'
end
end
module InstanceMethods
def qux
'qux'
end
end
end
class Something
include ConcernExample
end
Something.bar # => 'bar'
Something.qux # => NoMethodError: undefined method `qux'
Something.new.bar # => NoMethodError: undefined method `bar'
Something.new.qux # => 'qux'
Додаткові ресурси
- An Interactive Tutorial for Ruby - Learn Ruby through a series of interactive tutorials.
- Official Documentation
- Ruby from other languages
- Programming Ruby - An older free edition is available online.
- Ruby Style Guide - A community-driven Ruby coding style guide.
- Try Ruby - Learn the basic of Ruby programming language, interactive in the browser.