~16m5:18:02Functional Programming with Elixir – Full Course
10 мая 2023 г.
Read: ~16m · You save: 302 min
Функциональное программирование с Elixir – Полный курс
Изучите функциональное программирование с Elixir! Освойте рекурсию, сопоставление с образцом, акторную модель и создавайте мощные приложения.
Данный курс, разработанный Octolium, представляет собой всестороннее введение в язык программирования Elixir и парадигму функционального программирования. Слушатели познакомятся с ключевыми концепциями, такими как неизменяемость данных, рекурсия и сопоставление с образцом, а также с моделью акторов для построения параллельных и отказоустойчивых систем. Курс ориентирован на разработчиков с базовым опытом программирования, желающих освоить мощные инструменты для создания масштабируемых приложений.
Введение в Elixir
Курс, разработанный Octolium, охватывает основы Elixir и функционального программирования. В нем рассматриваются рекурсия, сопоставление с образцом и модель акторов. Курс также затрагивает типы данных, управление потоком выполнения и продвинутые темы, такие как смешанные проекты и операции со списками. По завершении курса слушатели смогут создавать собственные приложения на Elixir и уверенно применять концепции функционального программирования.
Курс предназначен для лиц, обладающих базовыми знаниями программирования на таких языках, как JavaScript, Python, Java или C++. Опыт программирования является обязательным, но экспертные знания не требуются.
В рамках курса будут изучены следующие темы:
- Основы функционального программирования.
- Основы Elixir, включая систему типов.
- Создание проектов с использованием Mix.
- Разработка библиотеки статистики в качестве заключительного проекта.
Elixir — это функциональный язык программирования. Приложения WhatsApp и Discord работают на одной виртуальной машине. Discord использует Elixir, а WhatsApp — Erlang. Erlang также является функциональным языком программирования.
Основы Elixir и Erlang
Elixir построен поверх Erlang и оба языка компилируются и работают на виртуальной машине Erlang, также известной как BEAM. Эта виртуальная машина аналогична виртуальной машине Java, на которой работают такие языки, как Java, Kotlin, Clojure и Scala. Elixir компилируется и выполняется на виртуальной машине BEAM.
Ключевыми преимуществами Elixir являются его функциональная природа и поддержка неизменяемости (immutability) по умолчанию. Неизменяемость данных обеспечивает высокую масштабируемость.
Параллелизм и акторы в Elixir
В Elixir отсутствует возможность для потоков или других объектов изменять значения, что обеспечивает сохранение состояния и повышает масштабируемость систем. Одной из ключевых особенностей Elixir является поддержка отказоустойчивости. Если узел или актор (процесс) выходит из строя, он может быть автоматически перезапущен с сохранением своего состояния. Это позволяет создавать распределенные и отказоустойчивые системы.
Функциональное программирование в Elixir означает, что вся программа состоит из различных функций. Функция принимает входные данные (аргумент), трансформирует их и возвращает результат. Этот процесс, хотя и выглядит простым, включает в себя создание чистых функций, которые всегда возвращают один и тот же результат для одних и тех же входных данных и не имеют побочных эффектов.
Функциональное программирование
В функциональном программировании отсутствуют классы и объекты. Все типы данных являются неизменяемыми, что означает работу с константами на протяжении всей программы.
Неизменяемые типы данных
Поскольку данные не являются изменяемыми, состояние остается прежним. Это позволяет копировать и распределять данные гораздо проще. Такое распределение данных дает возможность создавать масштабируемые системы с использованием функционального программирования.
В Elixir отсутствуют циклы for. Это связано с неизменяемостью данных. В традиционном цикле for переменная итерации постоянно изменяется (например, увеличивается). В Elixir, где данные неизменяемы, такой подход невозможен. Для выполнения итераций в Elixir используется рекурсия, которая будет подробно рассмотрена в следующем разделе.
Рекурсия
Рекурсия — это процесс, при котором одна и та же задача выполняется многократно, вызывая саму себя.
Сложность рекурсии заключается в её применении. В качестве примера можно привести концепцию "чудес света". Хотя существует общепризнанный список, личное восприятие чуда может варьироваться. Для таких выдающихся личностей, как Уоррен Баффет и Чарли Мангер, одним из чудес света является компаундинг (сложный процент).
Сравнение с привычками и системами
Восприятие мира индивидуально; Исаак Ньютон считал гравитацию величайшим чудом света. Автор же полагает, что рекурсия в сочетании с мутацией является одним из величайших чудес.
Человеческие привычки, повторяющиеся изо дня в день, можно рассматривать как состояние рекурсии. Изменение привычек происходит постепенно, посредством малых мутаций, что позволяет говорить о состоянии рекурсивной мутации.
Земля совершает полный оборот вокруг своей оси за 24 часа, возвращаясь в исходную точку, что является примером рекурсии. Орбитальное движение Земли вокруг Солнца занимает 12 месяцев, однако каждые четыре года добавляется дополнительный день (високосный год), что можно интерпретировать как рекурсивную мутацию.
Расширение Вселенной, начавшееся с Большого взрыва около 13,6 миллиардов лет назад, также может быть объяснено с помощью рекурсивной функции. Функция BigBang вызывается без аргументов, инициируя процесс расширения.
Установка Elixir
Для установки Elixir необходимо перейти на веб-сайт elixirlang.org и выбрать раздел "Install". Пользователям Windows следует загрузить установщик для Windows. Процесс установки включает последовательное нажатие кнопок "Next" и завершается нажатием "Finish". Пользователи macOS могут установить Elixir с помощью пакетного менеджера Homebrew. Для этого необходимо открыть терминал и выполнить команду brew install elixir.
После установки Elixir рекомендуется проверить версию, открыв терминал (или PowerShell в Windows) и введя команду elixir -v. Текущая версия Elixir составляет 1.14.1. Представленные в курсе материалы будут совместимы с будущими версиями.
Далее следует настройка плагина Elixir для Visual Studio Code. Для этого необходимо открыть расширения в редакторе.
Работа с файлами Elixir в VS Code
Для начала работы с Elixir в VS Code необходимо установить расширение Elixir LS. Данное расширение имеет более 339 000 загрузок. После установки расширения при первом открытии файла Elixir в VS Code появится уведомление о сборке PLT (Project Loading Time). Этот процесс может занять некоторое время. После завершения сборки PLT можно приступать к работе с файлами Elixir.
Оператор сопоставления в Elixir
В математике равенство означает, что левая часть эквивалентна правой. Например, в выражении a = 1 левая часть (a) равна правой части (1). Математика не определяет присваивание значения правой части левой. Если a = 1, то и 1 = a должно быть истинным.
В Elixir оператор = не является оператором присваивания, а оператором сопоставления. Он сопоставляет правую часть с левой. Этот механизм, известный как сопоставление с образцом, является мощным инструментом в Elixir. Каждое выражение с оператором = следует интерпретировать как попытку сопоставить правую часть с левой.
Для демонстрации этого оператора можно использовать интерактивную оболочку Elixir (REPL).
Интерактивная оболочка IEX
Для запуска интерактивной оболочки IEX необходимо ввести команду iex в терминале. Для очистки экрана терминала используется команда clear.
В IEX можно выполнять присваивание значений переменным. Например, присвоить значение 1 переменной a:
iex> a = 1
1
Затем можно проверить равенство значений с помощью оператора ==. Если a равно 1, то выражение a == 1 вернет true.
iex> a == 1
true
Если переменная a уже содержит значение 1, то выражение 1 == a также вернет true, поскольку оба операнда имеют одинаковое значение.
iex> 1 == a
true
Оператор == выполняет проверку на равенство, а не присваивание.
IEX поддерживает сопоставление с образцом. Например, при работе со списками, которые обозначаются квадратными скобками [], можно сопоставить переменные с элементами списка. Если список содержит два элемента, и обе переменные на левой стороне имеют одинаковое имя, например a, то значение первого элемента списка будет присвоено переменной a, а значение второго элемента также будет присвоено переменной a. В случае, если значения элементов списка совпадают, сопоставление будет успешным.
Пример сопоставления с образцом для списка:
iex> [a, a] = [1, 1]
[1, 1]
В данном случае, поскольку оба элемента списка равны 1, переменная a получит значение 1. Выражение вернет исходный список [1, 1].
Для выхода из IEX используется комбинация клавиш Ctrl + C дважды.
Введение и настройка
Сопоставление с образцом в Elixir позволяет сравнивать левую и правую части выражения. Если они идентичны, происходит сопоставление. Например, выражение a = 1 присваивает значение 1 переменной a. При попытке сопоставить a с 1, результат будет успешным, и значение a будет равно 1.
При сопоставлении a и a с 1 и 2 соответственно, возникает ошибка. Это происходит потому, что значение 1 присваивается переменной a, а затем вторая часть пытается сопоставить a (которое уже равно 1) со значением 2. Поскольку 1 не равно 2, сопоставление не удается, и генерируется ошибка "no match of the right hand side".
Если изменить правую часть, заменив вторую a на новую переменную b, например, a и a с 1 и 2, то сопоставление будет успешным. В этом случае 1 присваивается переменной a, а 2 — переменной b. Проверить это можно, обратившись к переменным a и b, которые будут содержать соответствующие значения.
Сопоставление с образцом является мощным инструментом в Elixir, который используется повсеместно.
Для более удобной работы с Elixir, помимо терминала, можно использовать Livebook. Livebook представляет собой аналог Jupyter Notebook для Elixir. Для установки Livebook необходимо перейти на сайт livebook.dev, выбрать операционную систему (macOS или Windows) и скачать установочный файл. После установки программу можно запустить.
В Livebook можно создавать новые блокноты, нажав "New notebook". Для выполнения кода используется кнопка "evaluate". Например, выражение a, a = 1, 1 будет успешно выполнено. Также можно выполнять более сложные выражения, например, if a == 1 do 1 == a end.
Для данного учебного курса доступны примеры блокнотов на GitHub по адресу github.com/octallium/functional-programming-with-Elixir. В репозитории, в папке notebooks, находятся три блокнота. Эти блокноты можно открыть в Livebook, выбрав соответствующий файл через иконку слева и указав путь к репозиторию. Блокноты содержат текстовые описания и блоки кода для практики.
Продолжая изучение сопоставления с образцом, можно вернуться к терминалу и запустить интерактивную оболочку IEX командой iex. В терминале можно выполнить сопоставление a, a = 1, 2, которое, как и ожидалось, приведет к ошибке "no match of the right hand side".
Основы Elixir: Неизменяемость и сопоставление с образцом
В Elixir переменная a связывается со значением 1. При попытке сопоставить значение 2 с переменной a, возникает ошибка несоответствия (match error), поскольку a уже связано со значением 1.
Это происходит из-за того, что все типы данных в Elixir являются неизменяемыми. Невозможно изменить значение существующей переменной после её инициализации. Неизменяемость данных в Elixir способствует масштабируемости системы.
При использовании оператора сопоставления (=), если переменная находится слева от оператора, Elixir связывает новое значение с этой переменной. Например, если a связано со значением 1, и мы пишем a = 2, то a теперь будет связано со значением 2.
Для предотвращения такого поведения и обеспечения строгого соответствия значений используется оператор закрепления (pin operator, ^). Например, ^a = 3 вызовет ошибку несоответствия, если a связано со значением, отличным от 3. Это происходит потому, что оператор закрепления проверяет, соответствует ли существующее значение переменной указанному значению, а не присваивает новое значение.
Если оператор сопоставления используется в обратном порядке, например, 3 = a, и a связано со значением 2, также возникнет ошибка несоответствия, поскольку 3 не равно 2.
Неизменяемость данных в Elixir упрощает их копирование между различными процессами без опасений о том, что другие ресурсы могут изменить эти данные.
Процессы и изоляция в Elixir
Код в Elixir выполняется внутри сущностей, называемых акторами. Актор можно представить как изолированный вычислительный блок. Он получает сообщения, обрабатывает их и возвращает ответ. Актор работает внутри процессов. Одновременно может существовать миллионы процессов.
Данные в Elixir неизменяемы. Это позволяет создавать множество копий данных и распределять их между различными акторами. Эти акторы могут работать как на локальной машине, так и в глобальном кластере серверов, обеспечивая горизонтальное масштабирование нагрузки.
Процессы в Elixir не являются процессами операционной системы. Их можно рассматривать как виртуальные потоки. Каждый процесс имеет уникальный идентификатор, называемый PID (Process ID). Взаимодействие между процессами осуществляется посредством передачи сообщений.
Поскольку данные неизменяемы, можно создавать множество копий и назначать их разным процессорам. Каждый актор получает свою копию данных, что исключает проблемы с одновременным изменением состояния. Все выполняется в изоляции.
Каждый процесс имеет собственное выделение стека и кучи. В отличие от компилируемых языков, таких как C или C++, где память выделяется на стеке или в куче, в Elixir каждый процесс получает собственное выделение стека и кучи. Это ускоряет сборку мусора, так как требуется очистка памяти только для одного процесса, что сохраняет отзывчивость приложения.
Каждый актор имеет свою почту (mailbox). Все сообщения, отправленные независимому процессу, собираются в этой почте и обрабатываются последовательно по принципу "первым пришел — первым ушел" (FIFO).
Создание процессов очень дешево и требует менее 3 КБ памяти. Это позволяет создавать миллионы процессов одновременно. Взаимодействие всегда происходит посредством передачи сообщений.
Идентификатор процесса (PID) можно проверить с помощью встроенной функции self. Скобки вокруг вызова функции не обязательны. Например, self и self() эквивалентны. В настоящее время принято использовать скобки при написании кода в редакторе, но в терминале это необязательно. PID текущего процесса, в котором запущена интерактивная оболочка IEX, имеет вид 0.107.0.
Создание и компиляция файлов Elixir
В Elixir код организуется в модули. Для определения модуля используется ключевое слово defmodule, за которым следует имя модуля и блок do...end. По соглашению, имя модуля должно совпадать с именем файла.
Для определения функций внутри модуля используется ключевое слово def. Функции могут принимать аргументы, которые указываются в скобках после имени функции. Если функция не принимает аргументов, скобки можно опустить. Блок кода функции также заключается в do...end.
Строки в Elixir определяются с использованием двойных кавычек. Одинарные кавычки предназначены для символов.
Создание скриптовых файлов
Elixir поддерживает два типа расширений файлов: .exs для скриптовых файлов и .ex для компилируемых файлов. Скриптовые файлы, имеющие расширение .exs, предназначены для выполнения кода напрямую, без предварительной компиляции. Они часто используются для задач разработки, таких как заполнение базы данных или тестирование.
Для запуска скриптового файла используется команда elixir <имя_файла.exs>. Если код внутри скрипта включает вызов функции, необходимо явно указать модуль и функцию для выполнения. Например, для вызова функции world из модуля hello используется синтаксис Hello.world().
Компиляция файлов
Elixir является компилируемым языком. Файлы с расширением .ex предназначены для компиляции. Для компиляции файла используется команда elixirc <имя_файла.ex>. Эта команда компилирует исходный код в байт-код, который затем может быть выполнен.
Обзор инструментов Elixir
Elixir-код компилируется в файлы .beam, которые исполняются на виртуальной машине Beam. Обычно для компиляции и запуска Elixir-файлов используется инструмент mix.
Скомпилированный файл hello.exs можно выполнить в интерактивной оболочке IEX. При попытке перекомпиляции модуля, который уже находится в памяти, появляется предупреждение о повторном определении модуля, которое можно игнорировать. После выполнения файла в IEX отображается вывод hello Elixir.
Функции в Elixir можно вызывать, указывая модуль и имя функции. Скобки вокруг аргументов необязательны. Например, вызов hello.world без аргументов возвращает hello Elixir и атом ok. Атомы — это один из типов данных в Elixir.
Функции могут принимать параметры. При использовании строковой интерполяции для включения параметра в строку используется синтаксис #{parameter_name}. Для перекомпиляции измененного модуля в IEX используется команда r. Например, r Hello перекомпилирует модуль Hello. После перекомпиляции можно вызвать функцию с параметром, например, hello.world("Octalium"), что вернет hello Octalium.
Все типы данных в Elixir являются неизменяемыми, то есть константами.
## Атомы в Elixir
Атом в Elixir представляет собой литерал, имя которого совпадает с его значением. Атомы начинаются с двоеточия (`:`), за которым следует имя. Например, `:nike` является атомом.
Если имя атома содержит пробелы, оно заключается в двойные кавычки. Например, `:"the nike"` является допустимым атомом.
Концептуально, атом подобен символу или логотипу, который однозначно идентифицирует определенное значение. В псевдокоде это можно представить как переменную `nike` со значением `nike`. В Elixir это выражается как атом `:nike`.
Атомы широко используются в Elixir, особенно для сопоставления с образцом. Они часто применяются для обозначения состояний или сообщений об ошибках. Например, для представления ошибки можно использовать атом `:error`.
Пример создания атома в интерактивной оболочке IEX:
```elixir
iex> :nike
:nike
iex> :"the nike"
:"the nike"
iex> :error
:error
Атомы часто возвращаются в виде кортежей для обозначения результата операции, например, при возникновении ошибки.
## Кортежи (Tuples) в Elixir
Кортежи в Elixir представляют собой неизменяемые структуры данных, состоящие из фиксированного числа элементов. Они часто используются для возврата значений из функций, особенно для обозначения успеха или ошибки операции.
Типичный паттерн использования кортежей включает возврат двух- или трехэлементного кортежа. Первый элемент часто указывает на результат операции: например, атом `:error` для обозначения ошибки или атом `:ok` для обозначения успеха. Последующие элементы содержат дополнительную информацию, такую как причина ошибки или возвращаемое значение.
Пример использования кортежа для обозначения ошибки:
```elixir
{:error, "file not found"}
В этом примере первый элемент, :error, сигнализирует об ошибке, а второй элемент, строка "file not found", описывает причину.
Сопоставление с образцом (pattern matching) является основным способом работы с кортежами в Elixir. Можно сопоставить структуру кортежа на левой стороне выражения с кортежем на правой стороне. При этом элементы кортежа могут быть привязаны к переменным.
Рассмотрим пример сопоставления с образцом для кортежа ошибки:
tuple = {:error, "file not found"}
{:error, reason} = tuple
В этом коде переменная reason будет привязана к значению "file not found". Проверка значения переменной reason подтвердит это:
reason
Результат:
"file not found"
Аналогично, кортежи используются для обозначения успешного выполнения операций. Например, при работе с веб-приложениями успешный ответ может быть представлен следующим образом:
{:ok, "status 200 ok"}
Здесь атом :ok указывает на успех, а строка "status 200 ok" содержит сообщение о статусе.
Пример сопоставления с образцом для успешного кортежа:
success_tuple = {:ok, "status 200 ok"}
{:ok, message} = success_tuple
В данном случае переменная message получит значение "status 200 ok". Вывод значения message покажет:
message
Результат:
"status 200 ok"
Этот паттерн, где первый элемент кортежа указывает на статус операции (ошибка или успех), а последующие элементы содержат связанные данные, широко распространен в Elixir.
Строки и списки в Elixir
В Elixir строки представляются с помощью двойных кавычек. Например, "octalium" является допустимой строкой. Использование одинарных кавычек вместо двойных определяет список символов, который отличается от строки.
Интерактивная оболочка Elixir (IEX) предоставляет функции для проверки типов данных. Функция is/1 может быть использована для получения информации о переменной. При вызове is("octalium") в IEX, результатом будет вывод, указывающий, что переменная имеет значение "octalium" и тип данных "binary string".
Строки в Elixir хранятся как коллекции байтов. Это означает, что тип данных "binary string" фактически представляет собой последовательность байтов в памяти. Строка в Elixir является бинарным представлением, закодированным в UTF-8. Размер строки "octalium" составляет 9 байтов. В памяти строки начинаются с двойных угловых скобок и заканчиваются ими.
Работа с байтами и протоколами
Строки в Elixir представляются как коллекции байтов. Каждому символу строки соответствует целочисленное представление. Например, число 79 обозначает 'O', а 99 — 'c'. Для типа строки реализовано несколько протоколов, которые являются более продвинутой темой и не рассматриваются в данном руководстве.
Строки можно рассматривать как последовательности байтов, и с помощью сопоставления с образцом (pattern matching) можно извлекать отдельные кодовые точки из строки. Например, можно сопоставить строку, указав первый символ ('o') и собрав оставшуюся часть строки в переменную rest. В результате переменная rest будет содержать все символы, следующие за 'o'.
iex> "octalium"
"octalium"
iex> ?o
79
iex> ?c
99
iex> is_binary("octalium")
true
iex> message = "hello" <> name
"hello octalium"
iex> "hello " <> name = message
"hello octalium"
iex> name
"octalium"
При сопоставлении с образцом строки можно использовать как обычное представление, так и сырое представление байтов. Сырое представление строки используется с двойными угловыми скобками << >>.
iex> <<head::binary, rest::binary>> = "octalium"
"octalium"
iex> head
"o"
iex> rest
"ctalium"
При работе со строками можно использовать оператор конкатенации «>> для объединения строк.
iex> message = "hello" <> name
"hello octalium"
Также можно использовать сопоставление с образцом для извлечения частей строки.
iex> "hello " <> name = message
"hello octalium"
iex> name
"octalium"
При сопоставлении с образцом сырого представления строки можно указать размер собираемых байтов.
iex> <<head::binary-size(2), rest::binary>> = "onc"
"onc"
iex> head
"on"
Введение в Elixir
## Введение в Elixir Курс от Octolium посвящен основам Elixir и функционального программирования. Он охватывает рекурсию, сопоставление с образцом, акторную модель, типы данных, управление потоком и продвинутые темы, такие как смешанные проекты и операции со списками. Цель курса — научить слушателей создавать собственные приложения на Elixir и уверенно применять концепции функционального программирования. Курс предназначен для людей с базовыми знаниями программирования на любом языке (JavaScript, Python, Java, C++). В рамках курса будут рассмотрены основы функционального программирования и Elixir, система типов Elixir, создание проектов с помощью Mix, а также разработка итогового проекта — библиотеки статистики. Elixir — это функциональный язык программирования. Примеры приложений, использующих Elixir или Erlang (на котором основан Elixir), включают Discord (на Elixir) и WhatsApp (на Erlang).
- Курс посвящен основам Elixir и функционального программирования.
- Курс создан Octolium.
- Темы курса включают: рекурсию, сопоставление с образцом, акторную модель, типы данных, управление потоком, смешанные проекты, операции со списками.
- Цель курса: научить создавать приложения на Elixir и применять концепции функционального программирования.
- Целевая аудитория: люди с базовыми знаниями программирования.
- Предварительные знания: базовый опыт программирования на любом языке (JavaScript, Python, Java, C++).
- План курса: основы функционального программирования, основы Elixir, система типов Elixir, создание проектов с помощью Mix, разработка библиотеки статистики как итогового проекта.
- Elixir — это функциональный язык программирования.
- Discord работает на Elixir.
- WhatsApp работает на Erlang.
- Erlang — это также функциональный язык программирования.
Основы Elixir и Erlang
## Основы Elixir и Erlang Elixir и Erlang работают на виртуальной машине BEAM, аналогично тому, как Java, Kotlin, Clojure и Scala работают на JVM. Elixir является функциональным языком программирования и по умолчанию поддерживает неизменяемость данных, что обеспечивает высокую масштабируемость.
- Alexa построена на базе Erlang.
- Elixir и Erlang являются компилируемыми языками.
- Elixir и Erlang работают на виртуальной машине BEAM (также известной как Erlang VM).
- Виртуальная машина BEAM аналогична виртуальной машине Java (JVM).
- Множество языков, таких как Java, Kotlin, Clojure и Scala, компилируются и работают на JVM.
- Elixir компилируется и работает на виртуальной машине BEAM.
- Elixir является функциональным языком программирования.
- Elixir по умолчанию поддерживает неизменяемость (immutability).
- Неизменяемость данных способствует высокой масштабируемости.
Параллелизм и акторы в Elixir
## Параллелизм и акторы в Elixir В Elixir состояние сохраняется, поскольку потоки или другие объекты не могут изменять значения напрямую, что обеспечивает масштабируемость. Elixir поддерживает отказоустойчивость: при сбое узла или актора он автоматически перезапускается с сохранением своего состояния, что позволяет создавать распределенные и отказоустойчивые системы. Функциональное программирование в Elixir означает, что программа состоит из функций. Функция принимает входные данные (аргумент), преобразует их и возвращает результат. Создание чистых функций включает в себя множество аспектов.
- Системы Elixir масштабируемы, так как потоки или другие объекты не могут изменять значения напрямую, сохраняя состояние.
- Elixir поддерживает отказоустойчивость.
- При сбое узла или актора в Elixir он автоматически перезапускается с сохранением своего состояния.
- Elixir позволяет создавать распределенные и отказоустойчивые системы.
- Функциональное программирование означает, что программа состоит из функций.
- Функция принимает входные данные, преобразует их и возвращает результат.
- Существуют аспекты, связанные с созданием чистых функций.
Функциональное программирование
## Функциональное программирование В функциональном программировании отсутствуют классы и объекты. Все типы данных являются неизменяемыми, что означает работу с константами на протяжении всей программы.
- В функциональном программировании нет классов или объектов.
- Все типы данных неизменяемы.
- В функциональном программировании работа происходит с константами.
Неизменяемые типы данных
## Неизменяемые типы данных Неизменяемые типы данных, или константы, означают, что состояние данных остается неизменным. Это позволяет легко копировать и распространять данные, что способствует созданию масштабируемых систем с использованием функционального программирования. В функциональном программировании и Elixir отсутствуют традиционные циклы `for`, так как они предполагают мутацию переменных (например, инкремент счетчика `i`). Вместо этого для итераций используются рекурсивные вызовы, которые будут подробно рассмотрены в следующем видео.
- Неизменяемые типы данных означают, что состояние данных остается неизменным.
- Неизменяемость данных позволяет легко копировать и распространять их.
- Использование неизменяемых данных способствует созданию масштабируемых систем.
- В функциональном программировании и Elixir отсутствуют циклы
for. - Циклы
forпредполагают мутацию данных (например, изменение переменнойiвi++). - В Elixir для итераций используются рекурсивные вызовы вместо циклов
for. - Рекурсия будет подробно рассмотрена в следующем видео.
Рекурсия
## Рекурсия Рекурсия — это выполнение одной и той же задачи снова и снова, когда задача вызывает саму себя. Уоррен Баффет и Чарли Мангер считают **компаундинг** (сложный процент) одним из чудес света.
- Рекурсия — это выполнение одной и той же задачи снова и снова.
- В состоянии рекурсии задача вызывает саму себя.
- Уоррен Баффет и Чарли Мангер считают компаундинг одним из чудес света.
Сравнение с привычками и системами
## Сравнение с привычками и системами В этом разделе проводится аналогия между концепцией рекурсивной мутации и повседневными явлениями, такими как человеческие привычки и движение небесных тел. Автор предполагает, что повторяющееся поведение людей можно рассматривать как форму рекурсии, а изменения в привычках — как мутацию. Аналогично, вращение Земли и ее орбитальное движение вокруг Солнца, включая високосные годы, также представлены как примеры рекурсивных процессов с элементами мутации. Наконец, расширение Вселенной после Большого взрыва сравнивается с рекурсивной функцией, демонстрирующей рост из начального состояния.
- Исаак Ньютон считал бы гравитацию одним из величайших чудес света.
- Восприятие чуда зависит от человека: для автора это рекурсия, а точнее — рекурсивная мутация.
- Человеческие привычки, повторяющиеся изо дня в день, можно рассматривать как состояние рекурсии.
- Изменения в привычках, происходящие постепенно, можно рассматривать как мутацию.
- Сочетание повторяемости привычек и их постепенных изменений можно назвать рекурсивной мутацией.
- Земля совершает оборот вокруг своей оси примерно за 24 часа, что можно рассматривать как состояние рекурсии.
- Земля обращается вокруг Солнца примерно за 12 месяцев.
- Каждые четыре года на Земле происходит високосный год, добавляется один день, что можно рассматривать как мутацию в орбитальном движении.
- Вселенная находится в состоянии расширения.
- Примерно 13,6 миллиарда лет назад произошел Большой взрыв, после которого возникли Земля, звезды, Солнце и галактики.
- Расширение Вселенной можно объяснить с помощью рекурсивно написанной функции.
- Большой взрыв можно представить как функцию, не принимающую аргументов.
Установка Elixir
## Установка Elixir Для установки Elixir перейдите на сайт `elixirlang.org` и нажмите "Install". **Для Windows:** Скачайте установщик и следуйте инструкциям: "Далее", "Далее", "Готово". **Для macOS:** Используйте Homebrew. Откройте терминал и введите команду `brew install elixir`. **Проверка установки:** Откройте терминал (или PowerShell для Windows) и введите `elixir -v`. Текущая версия — 1.14.1. Функциональность, представленная в этом видео, будет работать и в будущих версиях. **Настройка Visual Studio Code:** Установите плагин для Elixir через раздел "Extensions" в VS Code.
- Для установки Elixir необходимо перейти на сайт elixirlang.org.
- На сайте elixirlang.org есть раздел "Install".
- Для пользователей Windows доступен установщик, который устанавливается путем нажатия "Next", "Next", "Finish".
- Пользователи Mac могут установить Elixir с помощью Homebrew, введя команду
brew install elixirв терминале. - Проверить установку Elixir можно, введя в терминале команду
elixir -v. - Текущая версия Elixir, показанная в видео, — 1.14.1.
- Представленные в видео материалы будут работать в будущих версиях Elixir.
- Для настройки Elixir в Visual Studio Code необходимо установить соответствующий плагин через раздел "Extensions".
Работа с файлами Elixir в VS Code
## Работа с файлами Elixir в VS Code Для начала работы с Elixir в VS Code необходимо установить расширение Elixir LS. После установки при первом открытии файла Elixir VS Code начнет сборку PLT (Program Loading Table), что может занять некоторое время. После завершения сборки PLT можно приступать к работе с файлами Elixir. Важно понимать, что концепции объектно-ориентированного программирования, такие как переменные, отличаются в функциональном мире Elixir. Например, присваивание `a = 1` в Elixir не означает создание переменной `a`, которой присваивается значение `1`.
- Для работы с Elixir в VS Code необходимо установить расширение Elixir LS.
- Расширение Elixir LS имеет 339 000 загрузок.
- После установки расширения Elixir LS при первом открытии файла Elixir в VS Code запускается процесс сборки PLT (Program Loading Table).
- Сборка PLT занимает некоторое время.
- После завершения сборки PLT можно работать с файлами Elixir в VS Code.
- Концепции объектно-ориентированного мира, такие как переменные, отличаются в функциональном мире Elixir.
- Пример: присваивание
a = 1в Elixir не означает создание переменнойaс присвоенным значением1в традиционном понимании.
Оператор сопоставления в Elixir
## Оператор сопоставления в Elixir В Elixir оператор `=` является оператором сопоставления, а не оператором присваивания, как в традиционной алгебре. Это означает, что он проверяет, соответствует ли правая часть левой части, а не присваивает значение переменной. Это фундаментальный аспект сопоставления с образцом в Elixir, мощной концепции, которая позволяет проверять соответствие структур данных. В интерактивной оболочке Elixir (REPL) можно продемонстрировать работу этого оператора.
- В базовой алгебре выражение "a = 1" означает, что левая часть равна правой части.
- В базовой алгебре не существует концепции присваивания значения правой части левой части.
- В базовой алгебре, если левая часть равна правой, то и правая часть равна левой.
- В Elixir оператор
=является оператором сопоставления, а не оператором присваивания. - Оператор сопоставления в Elixir проверяет соответствие правой части левой части.
- Сопоставление с образцом является мощной концепцией в Elixir.
- В Elixir оператор
=всегда означает сопоставление правой части с левой. - Elixir поставляется с интерактивной оболочкой (REPL) для использования языка.
Интерактивная оболочка IEX
## Интерактивная оболочка IEX ### Вход и выход из IEX Для входа в интерактивную оболочку IEX введите `iex`. Для выхода нажмите `Ctrl+C` дважды. ### Очистка экрана Для очистки экрана терминала в IEX используйте команду `clear`. ### Присваивание и сравнение в IEX В IEX оператор `=` используется для присваивания значений переменным, а `==` — для сравнения. Пример: * `a = 1`: Присваивает значение `1` переменной `a`. * `1 == a`: Сравнивает `1` с переменной `a`. Результат будет `true`, если `a` равно `1`. * `1 = a`: В этом случае `1` и `a` имеют одинаковое значение, и оператор сравнения возвращает `true`. ### Сопоставление с образцом (Pattern Matching) IEX поддерживает сопоставление с образцом. Это означает, что вы можете сравнивать структуру данных на правой стороне выражения со структурой на левой. Пример со списком: * `[a, a] = [1, 1]`: Здесь происходит сопоставление списка `[1, 1]` с образцом `[a, a]`. Значение `1` присваивается переменной `a`. Поскольку обе переменные на левой стороне имеют имя `a`, и обе имеют значение `1` на правой стороне, результат будет `true`. Важно понимать, что `==` — это оператор сравнения, а не присваивания. Он проверяет, соответствует ли правая часть левой.
- Для входа в интерактивную оболочку IEX используется команда
iex. - Для выхода из IEX нажмите
Ctrl+Cдважды. - Команда
clearочищает терминал в IEX. - В IEX переменная
aможет быть равна1. - Сравнение
1 == aвозвращаетtrue, еслиaравно1. - Сравнение
1 = aвозвращаетtrue, если1иaимеют одинаковое значение. - Оператор
=в IEX используется для присваивания, а==— для сравнения. - IEX поддерживает сопоставление с образцом.
- Квадратные скобки
[]обозначают список в IEX. - Пример сопоставления с образцом:
[a, a] = [1, 1]возвращаетtrue. - В примере
[a, a] = [1, 1]значение1присваивается переменнойa. - В IEX можно использовать переменную
my_nameи присвоить ей значениеoctallium. - Сравнение
octallium == my_nameвернетtrue.
Введение и настройка
В этом разделе представлено введение в сопоставление с образцом в Elixir, демонстрирующее его использование в IEx и Livebook. Объясняется, как сопоставление с образцом работает путем сравнения левой и правой частей выражения, и как ошибки возникают, когда они не совпадают. Также представлен Livebook как альтернатива IEx для интерактивной разработки Elixir, с инструкциями по установке и использованию. Приведены ссылки на репозиторий GitHub с примерами блокнотов Livebook.
- Сопоставление с образцом в Elixir требует, чтобы левая и правая части выражения были равны.
- Пример:
a = 1успешно присваивает значение 1 переменнойa. - Пример:
a = 1, a = 2приводит к ошибке, так как значениеa(1) не совпадает с ожидаемым значением (2). - Пример:
a = 1, b = 2успешно связывает 1 сaи 2 сb. - Livebook — это инструмент, подобный Jupyter Notebook для Elixir.
- Livebook можно установить с сайта livebook.dev, выбрав соответствующую операционную систему.
- В Livebook можно создавать новые блокноты и выполнять код Elixir.
- Пример кода в Livebook:
a = 1, a = 1успешно выполняется. - Пример кода в Livebook:
a = 1, 1 = aуспешно выполняется. - Репозиторий GitHub для серии учебных пособий находится по адресу: octallium/functional-programming-with-elixir.
- В репозитории содержатся примеры блокнотов Livebook для использования.
- Блокноты Livebook можно открыть в приложении Livebook, выбрав путь к файлу блокнота.
Основы Elixir: Неизменяемость и сопоставление с образцом
## Основы Elixir: Неизменяемость и сопоставление с образцом ### Неизменяемость данных в Elixir В Elixir все типы данных являются неизменяемыми. Это означает, что после присвоения значения переменной, его нельзя изменить. Попытка присвоить новое значение существующей переменной приведет к ошибке сопоставления (match error). ### Оператор сопоставления и его особенности Оператор `=` в Elixir используется для сопоставления с образцом. Если переменная находится слева от оператора `=`, Elixir интерпретирует это как привязку нового значения к переменной. Например, `a = 1` привязывает значение `1` к переменной `a`. ### Оператор прикрепления (`^`) Для предотвращения изменения значения переменной при использовании оператора сопоставления используется оператор прикрепления (`^`). Например, `^a = 2` приведет к ошибке сопоставления, если `a` уже имеет другое значение, поскольку оператор `^` проверяет, соответствует ли существующее значение переменной образцу, а не присваивает новое значение. ### Причины неизменяемости Неизменяемость данных в Elixir используется для обеспечения масштабируемости. Неизменяемые данные могут быть легко скопированы между различными процессами без опасений о том, что другие ресурсы изменят их.
- Значение переменной
aпривязано к значению1. - Попытка сопоставить значение
2с переменнойa, которая уже связана со значением1, приводит к ошибке сопоставления. - Все типы данных в Elixir являются неизменяемыми.
- Неизменяемость данных в Elixir используется для обеспечения масштабируемости.
- Оператор
=в Elixir используется для сопоставления с образцом. - Если переменная находится слева от оператора
=, Elixir привязывает новое значение к этой переменной. - Оператор прикрепления
^используется для проверки соответствия существующего значения переменной образцу, а не для присвоения нового значения. - Использование
^a = 3, когдаaравно2, приводит к ошибке сопоставления. - Привязка значения
2к переменнойaвозможна, так какaнаходится слева от оператора=. "3 = a" приводит к ошибке, так как 3 не равно 2. - Неизменяемость данных позволяет легко копировать данные между процессами без опасений.
Процессы и изоляция в Elixir
## Процессы и изоляция в Elixir ### Акторы и модель акторов Код в Elixir выполняется внутри сущностей, называемых акторами. Акторы можно представить как изолированные "коробки", которые получают сообщения (данные или инструкции), обрабатывают их и возвращают ответ. Это изолированные вычислительные единицы. ### Процессы в Elixir Акторы работают внутри процессов. В системе может одновременно существовать миллионы процессов. Эти процессы не являются процессами операционной системы, а скорее виртуальными потоками. Каждый процесс имеет уникальный идентификатор (PID). ### Изоляция и неизменяемость данных Данные в Elixir неизменяемы. Это позволяет создавать миллионы копий данных, распределенных по разным акторам и процессам, в том числе по разным серверам в кластере. Поскольку каждый актор получает свою копию данных, изменение состояния одним актором не влияет на другие, обеспечивая изоляцию. ### Память и сборка мусора Каждый процесс имеет собственное выделение стека и кучи. Это упрощает сборку мусора, так как она выполняется для каждого процесса отдельно, что делает приложение отзывчивым. ### Почтовый ящик актора У каждого актора есть свой почтовый ящик, куда собираются все входящие сообщения. Сообщения обрабатываются в порядке поступления (FIFO - First-In, First-Out). ### Стоимость процессов Процессы в Elixir очень дешевы в создании, требуют менее 3 КБ памяти. Это позволяет создавать миллионы процессов одновременно. ### Коммуникация между процессами Взаимодействие между процессами осуществляется посредством передачи сообщений. ### Идентификатор процесса (PID) Каждый процесс имеет уникальный идентификатор, называемый PID. В IEX (интерактивная среда Elixir) можно узнать PID текущего процесса с помощью функции `self`. Например, PID процесса IEX может быть `0.107.0`. ### Синтаксис вызова функций Скобки при вызове функций в Elixir не всегда обязательны. Например, `self` можно написать как `self()` или просто `self`. В редакторах кода принято использовать скобки, а в терминале — нет.
- Код в Elixir выполняется внутри акторов.
- Акторы — это изолированные вычислительные единицы, которые получают, обрабатывают сообщения и возвращают ответы.
- Акторы работают внутри процессов.
- В системе Elixir может одновременно существовать миллионы процессов.
- Процессы Elixir являются виртуальными потоками, а не процессами операционной системы.
- Каждый процесс имеет уникальный идентификатор (PID).
- Данные в Elixir неизменяемы.
- Неизменяемость данных позволяет создавать множество копий данных, распределенных по акторам и процессам.
- Изоляция процессов предотвращает влияние изменений состояния одного актора на другие.
- Каждый процесс имеет собственное выделение стека и кучи.
- Раздельная сборка мусора для каждого процесса повышает отзывчивость приложения.
- У каждого актора есть почтовый ящик для входящих сообщений.
- Сообщения обрабатываются в порядке FIFO (первым пришел — первым ушел).
- Создание процессов требует менее 3 КБ памяти, что делает их очень дешевыми.
- Коммуникация между процессами осуществляется через передачу сообщений.
- Функция
selfв IEX возвращает PID текущего процесса. - Скобки при вызове функций в Elixir не всегда обязательны (например,
selfилиself()).
Создание и компиляция файлов Elixir
## Создание и компиляция файлов Elixir ### Файлы скриптов и компилируемые файлы В Elixir существует два типа файлов: файлы скриптов с расширением `.exs` и компилируемые файлы с расширением `.ex`. Файлы `.exs` предназначены для выполнения скриптов, например, для заполнения базы данных или тестирования, и не предназначены для продакшена. Файлы `.ex` используются для создания компилируемых проектов, что будет рассмотрено при использовании инструмента `mix`. ### Модули и функции Весь код в Elixir находится внутри модулей. Модуль определяется с помощью ключевого слова `defmodule`, за которым следует имя модуля и блок `do...end`. По соглашению, имя файла должно совпадать с именем модуля. Внутри модуля функции определяются с помощью ключевого слова `def`. Функции, не принимающие аргументов, могут иметь пустые скобки или обходиться без них. Строки в Elixir заключаются в двойные кавычки, а символы — в одинарные. ### Запуск и компиляция скриптов Скрипты Elixir с расширением `.exs` можно запускать напрямую с помощью команды `elixir <имя_файла.exs>`. Для выполнения кода внутри скрипта необходимо вызвать соответствующую функцию. Для компиляции и одновременного запуска файла скрипта используется команда `elixirc <имя_файла.exs>`, которая сначала компилирует файл, а затем выполняет его.
- В Elixir существуют два расширения файлов:
.exsдля скриптов и.exдля компилируемых файлов. - Файлы
.exsиспользуются для разработки, например, для заполнения базы данных или тестирования, и не предназначены для продакшена. - Весь код в Elixir должен находиться внутри модулей, определяемых с помощью
defmodule. - Для определения функций используется ключевое слово
def. - Функции, не принимающие аргументов, могут иметь пустые скобки или обходиться без них.
- Строки в Elixir заключаются в двойные кавычки, а символы — в одинарные.
- По соглашению, имя файла должно совпадать с именем модуля.
- Скрипты
.exsможно запускать командойelixir <имя_файла.exs>. - Для вызова функции из модуля используется синтаксис
<имя_модуля>.<имя_функции>(). - Для компиляции и запуска скрипта
.exsиспользуется командаelixirc <имя_файла.exs>.
Обзор инструментов Elixir
Видео демонстрирует компиляцию и выполнение кода Elixir, а также взаимодействие с ним через интерактивную оболочку IEX. Показано, как скомпилировать файл `.exs` в байт-код `.beam`, который выполняется на виртуальной машине Beam. Объясняется, что для управления проектами обычно используется инструмент `mix`. Демонстрируется компиляция и выполнение файла `hello.exs` в IEX, включая обработку предупреждения о повторном определении модуля. Показано, как вызывать функции, например `hello.world`, с необязательными скобками и как передавать параметры с использованием интерполяции строк. Также объясняется, что результат `OK` в IEX представляет собой атом, и что все типы данных в Elixir являются неизменяемыми (иммутабельными).
- Elixir-код компилируется в файл
.beam, который выполняется на виртуальной машине Beam. - Для управления проектами в Elixir обычно используется инструмент
mix. - Файлы Elixir с расширением
.exsможно компилировать и выполнять непосредственно в интерактивной оболочке IEX. - При повторной компиляции модуля в IEX может появиться предупреждение о повторном определении модуля, которое можно игнорировать.
- Вызов функций в Elixir может осуществляться с использованием нотации
Module.function, при этом скобки вокруг аргументов необязательны, особенно если функция не принимает параметров. - Результат
OKв IEX является атомом, представляющим тип данных. - Все типы данных в Elixir являются неизменяемыми (иммутабельными).
- В Elixir поддерживается интерполяция строк с использованием синтаксиса
#{variable}. - Команда
Rв IEX используется для перекомпиляции модуля.
Атомы в Elixir
## Атомы в Elixir Атомы в Elixir представляют собой именованные константы. Они начинаются с двоеточия (`:`), за которым следует имя атома. Если имя атома содержит пробелы, оно заключается в двойные кавычки. Синтаксис атома: `:имя_атома` или `:'имя атома с пробелами'`. Атомы используются для представления фиксированных значений, часто встречаясь в сопоставлении с образцом (pattern matching), например, для обозначения ошибок (`:error`) или состояний.
- Атом в Elixir начинается с двоеточия (
:), за которым следует имя. - Если имя атома содержит пробелы, оно заключается в двойные кавычки, например,
:'имя атома с пробелами'. - Атомы используются для представления фиксированных значений.
- Атомы широко применяются в сопоставлении с образцом (pattern matching).
- Пример использования атома для обозначения ошибки:
:error.
Кортежи (Tuples) в Elixir
## Кортежи (Tuples) в Elixir Кортежи в Elixir часто используются для представления результатов операций, особенно для обозначения ошибок или успешных операций. Типичный паттерн включает двух- или трехэлементные кортежи. ### Использование кортежей для ошибок Кортеж может содержать атом `:error` в качестве первого элемента, за которым следует описание причины ошибки, например, строка `"file not found"`. Этот паттерн позволяет использовать сопоставление с образцом (pattern matching) для извлечения информации. Пример: ```elixir {:error, "file not found"} ``` Сопоставление с образцом: ```elixir {:error, reason} = {:error, "file not found"} # Теперь переменная `reason` содержит значение "file not found" ``` ### Использование кортежей для успешных операций Аналогично, кортежи используются для представления успешных результатов. Например, в веб-приложении успешный ответ может быть представлен кортежем с атомом `:ok` и сообщением или данными. Пример: ```elixir {:ok, "status 200 okay"} ``` Сопоставление с образцом для успешного результата: ```elixir {:ok, message} = {:ok, "status 200 okay"} # Теперь переменная `message` содержит значение "status 200 okay" ``` Сопоставление с образцом является ключевым механизмом для работы с кортежами в Elixir, позволяя легко извлекать значения из их структуры.
- Кортежи в Elixir используются для представления результатов операций.
- Типичные кортежи имеют два или три элемента.
- Кортежи часто используются для обозначения ошибок, где первый элемент — атом
:error, а второй — причина ошибки (например, строка"file not found"). - Сопоставление с образцом (pattern matching) широко применяется для работы с кортежами.
- При сопоставлении с образцом, структура слева должна соответствовать структуре справа.
- Переменные в образце слева связываются со значениями из кортежа справа.
- Кортежи также используются для представления успешных операций, например, с атомом
:okи сообщением (например,"status 200 okay"). - Пример успешного кортежа:
{:ok, "status 200 okay"}. - Сопоставление с образцом позволяет извлекать значения из успешных кортежей, связывая их с переменными (например,
message).
Строки и списки в Elixir
В Elixir строки представляются двойными кавычками. Одиночные кавычки используются для списков символов, которые отличаются от строк. Строки в Elixir хранятся как коллекция байтов и являются UTF-8 закодированными бинарными данными. Размер строки "octalium" составляет 9 байтов. В IEX функция `is` может использоваться для получения информации о типе данных переменной.
- Строки в Elixir представляются двойными кавычками.
- Одиночные кавычки в Elixir означают список символов, а не строку.
- Строки в Elixir хранятся как коллекция байтов.
- Строка в Elixir является UTF-8 закодированным бинарным значением.
- В IEX функция
isиспользуется для отображения информации о типе данных переменной. - Пример: строка "octalium" имеет тип данных "binary string" и размер 9 байтов.
Работа с байтами и протоколами
В этом разделе рассматриваются основы работы со строками и протоколами в Elixir, включая их представление в виде байтов, использование сопоставления с образцом для извлечения данных и конкатенацию строк. Также затрагиваются темы списков символов, процессов, списков (связанных списков), кортежей, списков ключевых слов и карт. Особое внимание уделяется сопоставлению с образцом для различных структур данных и использованию встроенных функций для работы с ними. В заключение обсуждаются структуры (structs) и их определение с помощью макросов `defmodule` и `defstruct`, а также основы управления потоком выполнения с помощью `case`, `cond` и `if/else`. Рассматривается создание нового проекта с помощью `mix new` и основы рекурсии, включая хвостовую рекурсию и рекурсивные деревья. Приводятся примеры реализации рекурсивных функций для вычисления факториала, суммы цифр и реверсирования списка. Также демонстрируется использование встроенных функций для работы со списками, таких как `Enum.map`, `Enum.reduce`, `Enum.filter` и `Enum.sort`, и создание собственных реализаций этих функций. В конце раздела обсуждается создание статистики, включая расчет среднего значения (population mean и sample mean), медианы и моды, а также основы работы со структурами (`structs`) для представления данных, таких как расходы и семь чудес света, с использованием встроенных модулей и функций для их обработки.
- Строки в Elixir представляются как коллекция байтов или кодовых точек.
- Целочисленное представление символов строки может быть получено с помощью
?символ. - Протоколы являются более продвинутой темой и не рассматриваются подробно.
- Сопоставление с образцом (pattern matching) используется для извлечения данных из строк.
- Конкатенация строк выполняется с использованием одинарных угловых скобок
<>. Двойные угловые скобки<<>>используются для представления сырых байтов. - Функция
is_binary/1проверяет, является ли переменная строкой (бинарным значением). - Списки символов (char lists) создаются с использованием одинарных кавычек и представляются как список целых чисел (кодовых точек).
- Списки символов объединяются с помощью оператора
++. - Функция
is_list/1проверяет, является ли переменная списком символов. - Процессы в Elixir имеют идентификатор процесса (PID), который можно получить с помощью
self(). - Списки в Elixir являются односвязными связанными списками (singly linked lists).
- Доступ к элементам списка по индексу напрямую не поддерживается; используются рекурсивные функции или модуль
Enum. - Модуль
Enumпредоставляет множество функций для работы с перечисляемыми типами данных. - Функция-помощник
h(help) используется для получения документации по модулям и функциям. - Сопоставление с образцом может использоваться для извлечения элементов из списков, игнорируя ненужные элементы с помощью
_. - Функции
head/1иtail/1возвращают первый элемент списка и оставшуюся часть списка соответственно. - Оператор
|(pipe) используется как операторconsдля добавления элемента в начало связанного списка. - Кортежи (tuples) создаются с использованием фигурных скобок
{}и имеют фиксированный размер. - Кортежи хранят данные непрерывно в памяти и часто используются для возврата нескольких значений из функции.
- Списки ключевых слов (keyword lists) представляют собой списки пар ключ-значение, где ключи обычно являются атомами.
- Доступ к значениям в списках ключевых слов осуществляется с помощью встроенных функций модуля
Keyword. - Карты (maps) создаются с использованием сигила
%{}, где ключи могут быть различных типов (атомы, строки и т.д.). - Ключи-атомы в картах позволяют использовать точечную нотацию (
map.key) для доступа к значениям. - Ключи-строки в картах требуют использования стрелочной нотации (
map["key"]) для доступа к значениям. - Структуры (structs) определяются внутри модулей с помощью макроса
defstructи наследуют имя модуля. - Структуры ведут себя подобно картам и поддерживают сопоставление с образцом.
- Управление потоком выполнения осуществляется с помощью
case,condиif/else. caseиспользуется для сопоставления с образцом выражения с различными случаями.condиспользуется для проверки нескольких условий последовательно.if/elseиспользуется для простых условных выражений.- Mix — это инструмент управления проектами в Elixir, используемый для создания новых проектов (
mix new). - Рекурсия — фундаментальный концепт функционального программирования, где функция вызывает саму себя.
- Базовый случай (base case) необходим для завершения рекурсии.
- Хвостовая рекурсия (tail recursion) — это рекурсия, где рекурсивный вызов является последней операцией в функции, что позволяет оптимизировать использование памяти.
- Функции в Elixir являются неизменяемыми (immutable).
- Модуль
IOиспользуется для ввода/вывода, например,IO.puts/1для вывода текста. - Проект Mix компилируется и запускается с помощью
iex -S mix. - Алиасы (
alias) используются для сокращения длинных имен модулей. - Перекомпиляция измененных модулей выполняется с помощью
recompile(). - Рекурсивные деревья помогают визуализировать выполнение рекурсивных функций.
- Функции могут быть перегружены путем определения нескольких версий с разными параметрами (сопоставление с образцом).
- Сумма элементов списка может быть вычислена рекурсивно.
- Факториал числа может быть вычислен рекурсивно.
- Реверсирование списка выполняется путем итеративного добавления элементов в начало аккумулятора.
- Функция
Enum.map/2применяет функцию к каждому элементу списка и возвращает новый список. - Функция
Enum.reduce/3сводит список к одному значению, применяя функцию к каждому элементу и аккумулятору. - Функция
Enum.filter/2возвращает новый список, содержащий только те элементы, для которых функция-предикат вернулаtrue. - Функция
Enum.sort/2сортирует список. - Функция
Enum.flat_map/2применяет функцию к каждому элементу и затем