diff --git a/modules/10-basics/20-modules/description.en.yml b/modules/10-basics/20-modules/description.en.yml index 2e80a2a..5045304 100644 --- a/modules/10-basics/20-modules/description.en.yml +++ b/modules/10-basics/20-modules/description.en.yml @@ -10,7 +10,7 @@ theory: | Modules are defined with a special contstruct _defmodule/do/end_: - ``` + ```elixir # use CamelCase for name defmodule HexletBasics do # Here goes module contains diff --git a/modules/10-basics/30-strings/description.ru.yml b/modules/10-basics/30-strings/description.ru.yml index 3703295..c9c52a8 100644 --- a/modules/10-basics/30-strings/description.ru.yml +++ b/modules/10-basics/30-strings/description.ru.yml @@ -19,7 +19,7 @@ theory: | Функция `String.upcase(str, mode)` работает в трех разных режимах. В режиме `:default` она переводит в верхний регистр все символы, для которых это возможно. В режиме `:ascii` она переводит только символы латинского алфавита: - ``` + ```elixir String.upcase("hello мир!", :default) # "HELLO МИР!" String.upcase("hello мир!", :ascii) # "HELLO мир!" ``` @@ -31,14 +31,12 @@ instructions: | Реализуйте функцию `concate_and_upcase`, которая принимает две строки, соединяет их вместе, удаляет пробелы в начале и в конце, и переводит в верхний регистр только символы латинского алфавита. - ``` - defmodule Solution do - def concate_and_upcase(str1, str2) do - # TODO реализация - end - end + ```elixir + Solution.concate_and_upcase(" привет ", "world!") + # => "привет WORLD!" - IO.puts(Solution.concate_and_upcase("привет ", "world!")) + Solution.concate_and_upcase("hello ", "мир! ") + # => "HELLO мир!" ``` tips: diff --git a/modules/10-basics/40-numbers/description.ru.yml b/modules/10-basics/40-numbers/description.ru.yml index 5f79d33..9a47729 100644 --- a/modules/10-basics/40-numbers/description.ru.yml +++ b/modules/10-basics/40-numbers/description.ru.yml @@ -21,7 +21,7 @@ theory: | ``` Для больших чисел можно использовать символ подчеркивания между разрядами для удобства чтения: - + ```elixir 100_500 1_000_000 @@ -66,14 +66,16 @@ instructions: | Каждый результат выводится на отдельной строке. - ``` - defmodule Solution do - - def do_math(a, b) do - # TODO реализация - end - - end + ```elixir + Solution.do_math(10, 10) + # => 2.0 + # => 1 + # => 0 + + Solution.do_math(42, 3) + # => 15.0 + # => 14 + # => 3 ``` diff --git a/modules/20-data-types/20-lists/description.ru.yml b/modules/20-data-types/20-lists/description.ru.yml index 724d9f5..5f08909 100644 --- a/modules/20-data-types/20-lists/description.ru.yml +++ b/modules/20-data-types/20-lists/description.ru.yml @@ -47,25 +47,22 @@ theory: | Зачем нужны такие странные операции? На них основана итерация по элементам списка. А на итерации основана вообще любая работа со списками и с другими коллекциями. Это станет понятно позже, когда мы начнем изучать рекурсию и основы функционального программирования. - -instructions: | - Реализовать функцию, которая возвращает сумму первого и второго элементов списка. +instructions: | - Внимательный слушатель спросит: "а что функция должна сделать, если в списке только один элемент, или список вообще пустой?". На этот вопрос мы ответим в следующем модуле, где будем изучать ветвления в коде и сопоставление с образцом. Пока будем считать, что функция всегда вызывается со списком, содержащим два или больше элементов. - - ```elixir - defmodule Solution do + Реализуйте функцию `get_second_item`, которая возвращает сумму первого и второго элементов списка. - def get_second_item(list) do - # TODO реализация - end + Внимательный читатель спросит: "а что функция должна сделать, если в списке только один элемент, или список вообще пустой?". На этот вопрос мы ответим в следующем модуле, где будем изучать ветвления в коде и сопоставление с образцом. Пока будем считать, что функция всегда вызывается со списком, содержащим два или больше элементов. - end + ```elixir + Solution.get_second_item([20, 22, 24]) + # => 42 + Solution.get_second_item([1, 2, 3, 4]) + # => 3 ``` - Еще более внимательный слушатель спросит: "а что, если список содержит элементы такого типа, для которого не определена операция суммирования?". В этом случае возникнет исключение. Исключения и обработку ошибок мы, конечно, тоже изучим. - - -tips: [] + Еще более внимательный читатель спросит: "а что, если список содержит элементы такого типа, для которого не определена операция суммирования?". В этом случае возникнет исключение. Исключения и обработку ошибок изучим в соответствующем модуле. +tips: + - | + [Официальная документация](https://hexdocs.pm/elixir/List.html) diff --git a/modules/20-data-types/30-maps/description.ru.yml b/modules/20-data-types/30-maps/description.ru.yml index 3f438f6..1a48a26 100644 --- a/modules/20-data-types/30-maps/description.ru.yml +++ b/modules/20-data-types/30-maps/description.ru.yml @@ -14,7 +14,7 @@ theory: | ``` Часто в качестве ключей используют атомы: - + ```elixir other_map = %{:a => 1, :b => 2} other_map[:a] # 1 @@ -22,9 +22,9 @@ theory: | ``` Для ключей атомов (и только в этом случае) можно использовать синтаксический сахар: - + ```elixir - other_map = %{a: 1, b: 2} + other_map = %{a: 1, b: 2} other_map.a # 1 other_map.b # 2 ``` @@ -37,7 +37,7 @@ theory: | ``` Как видим, в первом случае возвращается значение `nil`, а во втором случае генерируется исключение. - + Функция `Map.get` работает так же, как обращение через квадратные скобки. Но она позволяет указать дефолтное значение для отсутствующего ключа: ```elixir @@ -71,7 +71,7 @@ theory: | Такой синтаксис удобен тем, что позволяет изменять несколько ключей сразу. А добавить новый ключ этот синтаксис не позволяет: - + ```elixir %{other_map | :c => 42} # ** (KeyError) key :c not found in: %{a: 1, b: 2} ``` @@ -82,34 +82,47 @@ theory: | Map.delete(other_map, :a) # %{b: 2} ``` - -instructions: | - - Реализовать функцию `keys_sum`, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает сумму значений. Если ключа в словаре нет, то соответствующее значение не учитывается. - Реализовать функцию `keys_product`, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает произведение значений. Если ключа в словаре нет, то соответствующее значение не учитывается. - - Реализовать функцию `copy_key`, которая принимает два словаря, ключ, и значение по умолчанию. По ключу нужно извлечь значение из первого словаря и вставить во второй словарь. Если в первом словаре нет такого ключа, то во второй словарь нужно вставить значение по умолчанию. Если во втором словаре уже есть такой ключ, то его значение меняется. - - ```elixir - defmodule Solution do +instructions: | - def keys_sum(map, key1, key2) do - # TODO реализация - end + Реализуйте функцию `keys_sum`, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает сумму значений. Если ключа в словаре нет, то соответствующее значение не учитывается. - def keys_product(map, key1, key2) do - # TODO реализация - end + Реализуйте функцию `keys_product`, которая принимает словарь и два ключа, извлекает значения по этим ключам, и возвращает произведение значений. Если ключа в словаре нет, то соответствующее значение не учитывается. - def copy_key(from_map, to_map, key, default_value) do - # TODO реализация - end + Реализуйте функцию `copy_key`, которая принимает два словаря, ключ, и значение по умолчанию. По ключу нужно извлечь значение из первого словаря и вставить во второй словарь. Если в первом словаре нет такого ключа, то во второй словарь нужно вставить значение по умолчанию. Если во втором словаре уже есть такой ключ, то его значение меняется. - end + ```elixir + map = %{a: 1, b: 2, c: 42} + Solution.keys_sum(map, :a, :b) + # => 3 + Solution.keys_sum(map, :a, :c) + # => 43 + Solution.keys_sum(map, :c, :b) + # => 44 + + map = %{one: 1, five: 5, ten: 10} + Solution.keys_product(map, :one, :five) + # => 5 + Solution.keys_product(map, :five, :ten) + # => 50 + Solution.keys_product(map, :two, :ten) + # => 10 + + map1 = %{a: 1, b: 2} + map2 = %{c: 3, d: 4} + + Solution.copy_key(map1, map2, :a, 42) + # => %{c: 3, d: 4, a: 1} + Solution.copy_key(map1, map2, :b, 42) + # => %{c: 3, d: 4, b: 2} + + Solution.copy_key(map2, map1, :d, 42) + # => %{a: 1, b: 2, d: 4} + Solution.copy_key(map2, map1, :e, 42) + # => %{a: 1, b: 2, e: 42} ``` - + tips: - | [Официальная документация](https://hexdocs.pm/elixir/Map.html) diff --git a/modules/30-flow/10-pattern-matching/description.ru.yml b/modules/30-flow/10-pattern-matching/description.ru.yml index 9efc9a7..d0c6c02 100644 --- a/modules/30-flow/10-pattern-matching/description.ru.yml +++ b/modules/30-flow/10-pattern-matching/description.ru.yml @@ -34,9 +34,9 @@ theory: | IO.puts(age) # => 25 ``` - Первая строка опять выглядит как присваивание. Только значение более сложное -- кортеж из трех элементов. А вот вторая строка уже интереснее. + Первая строка опять выглядит как присваивание. Только значение более сложное -- кортеж из трех элементов. А вот вторая строка уже интереснее. - Слева от оператора `=` шаблон, который ограничивает множество значений. Этот шаблон может совпасть только с такими значениями, которые являются кортежами из трех элементов, первым элементом обязательно должен быть атом `:user`, а второй и третий элемент могут быть любыми. + Слева от оператора `=` шаблон, который ограничивает множество значений. Этот шаблон может совпасть только с такими значениями, которые являются кортежами из трех элементов, первым элементом обязательно должен быть атом `:user`, а второй и третий элемент могут быть любыми. Справа от оператора `=` находится значение, которое мы сравниваем с шаблоном. В данном случае значение извлекается из переменной `user`, но оно может быть и результатом вызова функции или литералом. @@ -69,7 +69,7 @@ theory: | Обратите внимания на символ подчеркивания. Он совпадает с любым значением, и применяется, когда это значение не нужно, мы не хотим сохранять его в переменную. - Если переменная встречается два раза, то значения в этих местах должны быть одинаковыми: + Если переменная встречается два раза, то значения в этих местах должны быть одинаковыми: ```elixir {a, a, 42} = {10, 10, 42} # match @@ -78,7 +78,7 @@ theory: | ``` Но это не касается символа подчеркивания: - + ```elixir {_, _, 42} = {10, 10, 42} # match {_, _, 42} = {20, 20, 42} # match @@ -90,7 +90,7 @@ theory: | ```elixir [pattern] = [value] ``` - + Шаблон может включать: - литералы - переменные @@ -107,30 +107,29 @@ theory: | - конструкция case - клозы функций (clause) - обработка исключений (rescue, catch) - - чтение сообщений из mailbox процесса (receive) + - чтение сообщений из mailbox процесса (receive) Конструкции case и function clause рассмотрим в следующей теме. Обработка исключений и чтение сообщений будут позже в курсе. instructions: | - Реализовать функцию `get_age(user)`, которая принимает объект `user`, представленный в виде кортежа `{:user, name, age}`, и возвращает возраст (age). + Реализуйте функцию `get_age(user)`, которая принимает объект `user`, представленный в виде кортежа `{:user, name, age}`, и возвращает возраст (age). - Реализовать функцию `get_names(users)`, которая принимает список из трёх объектов `user`, представленных такими же кортежами, и возвращает список из трёх имен. + Реализуйте функцию `get_names(users)`, которая принимает список из трёх объектов `user`, представленных такими же кортежами, и возвращает список из трёх имен. ```elixir - defmodule Solution do + bob = {:user, "Bob", 42} + helen = {:user, "Helen", 20} + kate = {:user, "Kate", 22} - def get_age(user) do - # TODO реализация - end + Solution.get_age(bob) # => 42 + Solution.get_age(helen) # => 20 + Solution.get_age(kate) # => 22 - def get_names(users) do - # TODO реализация - end - - end + Solution.get_names([bob, helen, kate]) + # => ["Bob", "Helen", "Kate"] ``` - + tips: - | [Про pattern matching](https://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D0%BF%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D1%81_%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D1%86%D0%BE%D0%BC) diff --git a/modules/30-flow/30-cond/description.ru.yml b/modules/30-flow/30-cond/description.ru.yml index 8dc29f3..ac8e59c 100644 --- a/modules/30-flow/30-cond/description.ru.yml +++ b/modules/30-flow/30-cond/description.ru.yml @@ -3,10 +3,10 @@ name: Конструкция cond theory: | - Если из конструкции *case* убрать шаблоны, но оставить охранные выражения, то получится конструкция *cond*. + Если из конструкции *case* убрать шаблоны, но оставить охранные выражения, то получится конструкция *cond*. Было: - + ```elixir case Expr do Pattern1 [when GuardSequence1] -> @@ -18,7 +18,7 @@ theory: | ``` Стало: - + ```elixir cond do GuardSequence1 -> @@ -30,7 +30,7 @@ theory: | ``` В принципе, это эквивалент цепочки `if...else if`, которая нередко встречается в императивных языках. Python, например: - + ```python a = int(input()) if a < -5: @@ -59,7 +59,7 @@ theory: | ## Конструкция if В Эликсир есть привычная всем конструкция *if*: - + ```elixir def gcd(a, b) do if rem(a, b) == 0 do @@ -70,10 +70,10 @@ theory: | end ``` - Только это не настоящая конструкция языка, а макрос. Впрочем, в Эликсир очень многое является макросами. В некоторых случаях это важно знать, в некоторых не важно. + Только это не настоящая конструкция языка, а макрос. Впрочем, в Эликсир очень многое является макросами. В некоторых случаях это важно знать, в некоторых не важно. Есть и конструкция *unless*, тоже макрос: - + ```elixir def gcd(a, b) do unless rem(a, b) != 0 do @@ -85,7 +85,7 @@ theory: | ``` Есть важное отличие от императивных языков -- в функциональных языках *if* всегда возвращает какое-то значение. - + ```elixir > a = 5 > b = 10 @@ -109,10 +109,10 @@ theory: | instructions: | Реализовать функцию `single_win?(a_win, b_win)`, которая принимает 2 булевых параметра: `a_win` -- победил ли игрок A, и `b_win` -- победил ли игрок B. Функция возвращает `true` если победил только один из двоих игроков, иначе возвращает `false`. - + Реализовать функцию `double_win?(a_win, b_win, c_win)`, которая принимает 3 булевых параметра для трех игроков. Если победили игроки A и B, то функция возвращает атом `:ab`. Если победили игроки A и C, то функция возвращает атом `:ac`, если победили игроки B и C, то функция возвращает атом `:bc`. Во всех остальных случаях функция возвращает `false`. - ``` + ```elixir defmodule Solution do def single_win?(a_win, b_win) do