Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new structure #159

Merged
merged 1 commit into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions modules/10-basics/10-hello-world/ru/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

Наберите в редакторе код из задания символ в символ и нажмите «Проверить».

```ruby
puts 'Hello, World!'
```
16 changes: 16 additions & 0 deletions modules/10-basics/10-hello-world/ru/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

По традиции начнем с написания программы 'Hello, World!'. Эта программа будет выводить на экран текст:

```ruby
# В конце инструкции нет символа ;
# В Ruby не ставятся ; практически никогда
puts 'Hello, World!'
```

`puts()` — функция печати на экран. В Ruby функции могут вызываться как со скобками, так и без них — разница только в способе записи. Код выше можно было бы записать так:

```ruby
puts('Hello, World!')
```

Решение о том, ставить скобки или нет, зависит от предпочтений программиста и удобства в каждой конкретной ситуации. Это понимание придёт со временем.
2 changes: 2 additions & 0 deletions modules/10-basics/10-hello-world/ru/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: Привет, Мир!
tips: []
8 changes: 8 additions & 0 deletions modules/10-basics/15-ruby-as-a-second-language/ru/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

На данном этапе мы знаем ещё слишком мало, чтобы писать какой-то интересный код, поэтому просто скопируйте и выполните код ниже. В этом коде используется библиотека ActiveSupport, которая расширяет язык некоторыми полезными возможностями. Изначально она была создана для Rails, но используется и за его пределами.

```ruby
# На сервере время в UTC
# Считаться будет от него
puts 1.day.ago - 1.week + 3.hours
```
76 changes: 76 additions & 0 deletions modules/10-basics/15-ruby-as-a-second-language/ru/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

Ruby на нашем проекте дается как «второй язык» — это значит, что мы подразумеваем определенный багаж знаний у тех, кто учится ему здесь. В первую очередь это владение каким-либо другим языком программирования. Для понимания материала курса нужно иметь представление о типах данных, переменных, условных конструкциях, циклах, функциях, объектах (свойствах и методах) и лямбда-функциях (анонимных функциях).

Изучение второго языка значительно проще первого, поэтому и структура материала сильно меняется. Здесь мы обзорно касаемся базовых конструкций для быстрого знакомства с синтаксисом, и переходим к интересным задачкам, ради которых, собственно, и изучается Ruby.

## В чём соль?

Ruby — динамический, строго типизированный язык с глубоким уклоном в объектно-ориентированную и функциональную парадигму программирования.

```ruby
# Строгая типизация, число нельзя умножить на строку
4 * 'hexlet' # TypeError (String can't be coerced into Integer)
# Всё объекты
1.8.round # 2
# Функции высшего порядка
['one', 'two'].map(&:upcase) # ["ONE", "TWO"]
```

Он обладает местами непривычным, но невероятно выразительным синтаксисом. Благодаря этому код на Ruby читается как английский язык и при этом остаётся компактным:

```ruby
# Определение конечного автомата
class Job
include AASM

aasm do
state :sleeping, initial: true
state :running, :cleaning

event :run do
transitions from: :sleeping, to: :running
end

event :sleep do
transitions from: [:running, :cleaning], to: :sleeping
end
end
end

job = Job.new
job.sleeping? # true
job.may_run? # true
job.run
job.running? # true
job.may_run? # false
```

На Ruby создано большое количество решений, которые потом распространились по другим языкам. Самым ярким примером является фреймворк Ruby On Rails, который когда-то перевернул веб-разработку, и до сих пор является самым продвинутым бэкенд фреймворком для веб-разработки. И github.com, и gitlab.com написаны с использованием Rails. Даже этот сайт написан на Rails.

В Ruby очень много метапрограммирования, встроенного во все части языка. Это значит, что программа может менять свое поведение прямо во время работы практически в любую сторону. Посмотрите, как происходит добавление методов во встроенные классы:

```ruby
# Этот код можно написать в любом месте программы
class String # встроенный в Ruby класс, отвечающий за строки
def wow # определение метода
'ruby power'
end
end

# Вызываем метод
'hexlet'.wow # 'ruby power'
```

И даже так:

```ruby
# Только для демонстрации
# Класс New наследуется от случайно выбранного
# класса One или Two, в зависимости от того,
# какой из них выберет метод sample на момент загрузки файла с классом
class New < [One, Two].sample
# тут код класса
end
```

На этом моменте у вас возможно возникла мысль «это же ад». Как и любой мощный инструмент, Ruby можно использовать во зло — это правда, но если посмотреть на реальное положение дел, то при правильном использовании Ruby позволяет писать невероятно выразительный код. И раз вы здесь, то давайте научимся это делать.
4 changes: 4 additions & 0 deletions modules/10-basics/15-ruby-as-a-second-language/ru/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: Ruby, Ruby, Ruby
tips:
- |
[Ruby-комьюнити](https://t.me/hexletcommunity/9)
11 changes: 11 additions & 0 deletions modules/10-basics/20-everything-is-object/ru/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

Напечатайте на экран следующий вызов:

```ruby
# Здесь выводятся на экран все методы строк,
# которые содержат знак вопроса в имени
# Фактически — это вывод списка предикатов
# То же самое можно сделать для любого типа
puts 'hexlet'.methods.grep(/\?/)
# Будет выведено около 20 имен
```
61 changes: 61 additions & 0 deletions modules/10-basics/20-everything-is-object/ru/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

Ruby по своим возможностям и подходам в разработке близок к JavaScript и Python, но имеет свои особенности. Разработчики языка во многом опирались на Smalltalk, Lisp (это семейство языков), Perl и другие подобные языки. Это привело к интересному результату. Во-первых, Ruby — **очень** объектно-ориентированный язык. В Ruby всё есть объект, включая `nil` (это аналог `null`), и каждая операция — это вызов метода:

```ruby
'hexlet'.reverse # telxeh
1.7.round # 2
nil.to_i # 0
1 + 1 # на самом деле 1.+(1)
```

Одна из сильных сторон Ruby – [стандартная библиотека](https://ruby-doc.org/). Она решает практически все возникающие задачи. В одних только строках 185 встроенных методов!

*Это одна из причин, почему Ruby чаще других выигрывает в [CodeBattle](https://codebattle.hexlet.io/)*

```ruby
# Количество методов у разных типов данных
# В примерах ниже вызывается метод methods,
# хотя кажется, что это обращение к свойству
''.methods.count # 185
1.methods.count # 145
[].methods.count # 191
```

В Ruby всё, кроме присваивания, это вызовы методов. Такой подход позволяет переопределять буквально любое поведение:

```ruby
# То, что на самом деле происходит, когда мы выполняем «операции»
1.+(5) # 6
1.>(3) # false
```

На этом основано очень много кода, особенно библиотечного. Например, у любого объекта можно определить синтаксис, аналогичный доступу к массиву `[]`. Или можно определить операции для дат, сделав работу с ними максимально простой (как в примере прошлого урока). А вот как выглядят сеттеры у объектов:

```ruby
# Кажется, что это прямое изменение свойства
# На самом деле это сеттер object.key=('value')
obj.key = 'value'
```

Все данные в Ruby — это объекты. Например `nil`, представлен классом `NilClass`, и является единственным его объектом. `true` — объект класса `TrueClass`, а `false` — объект класса `FalseClass`. У остальных типов свои классы.

Узнать класс любого объекта можно так:

```ruby
1.class # Integer
''.class # String
nil.class # NilClass
```

С другой стороны классы в Ruby — тоже объекты, у которых есть свои классы 0_o. Но это уже совсем другая история) Есть даже такая шутка (но это не шутка): в Ruby объект это класс, а класс — это объект. Почему это так – узнаем чуть позже.

## Отладочная печать

Иногда в работе приходится прибегать к отладочной печати и в Ruby есть несколько особенностей, о которых надо знать. Функция `puts()` выводит любые типы данных без необходимости преобразования их в строку. С другой стороны, такой вывод не останавливает выполнение и иногда это неудобно, если хочется посмотреть только первый вывод. Для таких ситуаций лучше использовать выброс исключения, которое и выведет на экран нужную информацию и прервёт выполнение. Делается это так:

```ruby
# raise – бросить исключение
# .inspect – метод, который преобразует
# любые данные в строковое представление
raise something.inspect
```
2 changes: 2 additions & 0 deletions modules/10-basics/20-everything-is-object/ru/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: Всё есть объект
tips: []
7 changes: 7 additions & 0 deletions modules/10-basics/25-first-function/ru/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Реализуйте функцию `double()`, которая удваивает любое переданное ей число и возвращает его:

```ruby
double(3) # 6
double(8) # 16
```
45 changes: 45 additions & 0 deletions modules/10-basics/25-first-function/ru/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

Начнем сразу с комплексного примера, включающего в себя определение функции, переменной и простые арифметические операции. Посмотрим на синтаксис и разберём некоторые интересные особенности Ruby. Ниже дано определение функции, находящей среднее арифметическое:

```ruby
# def – определение функции
def find_average(a, b)
# создание переменной sum
sum = a + b
# преобразование к Float
sum.to_f / 2
end

find_average(3, 1) # 2.0
find_average(1, 2) # 1.5

# Можно вызывать и так
find_average 3, 1
find_average 1, 2

# ArgumentError (wrong number of arguments (given 1, expected 2)
find_average(1)
```

Сначала пара слов о стиле. В Ruby существует ровно один общепринятый стиль оформления кода, которого [придерживается](https://ukupat.github.io/tabs-or-spaces/) все комьюнити:

* Отступы — два пробела
* Для определения имен переменных и функций используется snake_case
* Определение классов — CamelCase

Определение функции начинается ключевым словом `def`, за которым идёт имя функции и её параметры. В конце добавляется `end`. В отличие от своих собратьев, в Ruby не обязательно писать ключевое слово `return`. Как и в Smalltalk, в Ruby функции всегда возвращают результат последнего вычисленного выражения. Иногда `return` всё же используется, когда нужно досрочно выйти из функции. В остальных случаях его опускают.

Определение переменных в Ruby крайне простое. Достаточно написать имя и присвоить ему любое значение. Затем переменную можно использовать и менять как угодно и где угодно в поле её видимости.

```ruby
sum = a + b
```

Необычно в примере выше может выглядеть код `sum.to_f`. Здесь происходит вызов метода `to_f()` у числа, записанного в `sum`. Для чего это нужно? В Ruby при делении целых чисел на выходе всегда получается целое число. Если при этом была дробная часть, она отбрасывается:

```ruby
3 / 2 # 1
3.to_f / 2 # 1.5
```

По своему смыслу функция `find_average()` должна возвращать число с плавающей точкой, поэтому такое преобразование необходимо.
2 changes: 2 additions & 0 deletions modules/10-basics/25-first-function/ru/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: Первая функция
tips: []
7 changes: 7 additions & 0 deletions modules/10-basics/27-conditions/ru/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Реализуйте функцию предикат `even?`, которая проверяет, является ли переданное число чётным. Функция должна возвращать `true`, если число чётное и `false`, если не чётное. Не используйте встроенные функции для определения четности:

```ruby
even?(5) # false
even?(6) # true
```
60 changes: 60 additions & 0 deletions modules/10-basics/27-conditions/ru/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

## Логические операторы

Логический тип в Ruby представлен привычными значениями `true` и `false`, а также набором операторов `&&` (и), `==` (равно), `||` (или) и `!` (не):

```ruby
true && false # false
false || true # true
```

В отличие от многих других языков сравнение с логическим значением в Ruby строгое, то есть `true` и `false` равны только самим себе:

```ruby
true == 1 # false
false == nil # false
```

Что не отменяет возможности использовать в логических выражениях значения любых типов:

```ruby
0 && 'one' # "one"
nil && false # nil
```

В Ruby только `nil` и `false` рассматриваются как *falsey*, все остальные значения в логических выражениях приводятся к `true`.

## Значение по умолчанию

В Ruby широко используется такой код:

```ruby
a ||= 'что-то'
# a = a || 'что-то'
```

Он используется для задания значения по умолчанию. Такое возможно и почти всегда безопасно из-за очень ограниченного списка *falsey* значений. Единственное место, где этот способ не сработает – там, где `false` это допустимое значение.

## Предикаты

В Ruby в отличие от большинства других языков принято использовать предикаты практически для всех часто встречающихся проверок. Например, как мы обычно проверяем, что число равно нулю? С помощью сравнения с нулем. В Ruby это тоже работает, но это не Ruby Way:

```ruby
0.zero? # true
1.zero? # false
2.positive? # true

# чётное/нечётное
8.even? # true
8.odd? # false

''.empty? # true
'wow'.empty? # false

something.nil?

# не пустой массив
items.any?
# пустой массив
items.empty?
```
2 changes: 2 additions & 0 deletions modules/10-basics/27-conditions/ru/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: Логический тип
tips: []
16 changes: 16 additions & 0 deletions modules/10-basics/30-if/ru/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

В Ruby встроен оператор `<=>` (spaceship). Этот оператор удобно использовать в функциях сортировки для определения того, нужно менять местами два соседних элемента или нет. Всего у функции возможны три разных варианта возврата:

```ruby
1 <=> 1 # 0 числа равны
2 <=> 1 # 1 левое больше правого
1 <=> 2 # -1 левое меньше правого
```

Вашей задачей в этом задании будет написать функцию `compare()`, которая ведёт себя так же, как и spaceship-оператор:

```ruby
compare(1, 1) # 0 числа равны
compare(2, 1) # 1 левое больше правого
compare(1, 2) # -1 левое меньше правого
```
Loading
Loading