О том, как из C# перешел в Elixir/Phoenix +8


Как-то раз пришлось мне менять работу. До этого я работал только с языками типа Python, C++, C# и ещё парочкой подобных. А теперь пришлось начать работать с функциональным языком. Первые впечатления были «да что за фигня?». Однако у меня получилось достаточно быстро адаптироваться. Далее я расскажу об основных моментах, к которым пришлось привыкнуть или которые пришлось понять, чтобы начать писать быстро и адекватно.

1. Pattern matching

Это одна из основных фишек языка. Но полностью осознать её, пока не начнешь реально писать на языке немного сложно. Первое что я прочел сопоставление паттернов — это то что благодаря этой штуке можно достаточно просто извлекать данные из структур и связывать их с переменными. Но на самом деле все несколько сложнее. Сопоставление паттернов работает почти везде в данном языке. Приведу три примера иллюстрирующих основные применения, которыми я пользуюсь почти постоянно.

Пример 1. По определению:

{tuple_item_1, tuple_item_2} = tuple 

– разбивает 2-х элементный кортеж на две переменных, которые далее можно использовать.

[head_item | tail_list] = list 

– разбивает список на первый элемент в списке и список без первого элемента.

Пример 2. Сопоставление в case:

case get_elem(struct) do
  {:ok, elem} -> …
  {:error, reason} -> …
end

Функция get_elem(struct) возвращает кортеж, и case позволяет сразу извлечь данные и выбрать дальнейшую последовательность действий.

Пример3. Сопоставление функций:

def function_1(params, :ok) do
end

def function_1(params, :error) do
end

def function_1(params, _) do
end

Здесь по сути представлена одна и та же функция принимающая два параметра. Сопоставление паттернов позволяет выбрать, какую именно функцию исполнить.

Немного о работе сопоставления паттернов. Сопоставление идет всегда «сверху-вниз». В данном примере при вызове function_1 от двух параметров, сначала произойдет проверка, что второй параметр равен :ok. Если первая проверка провалится, то произойдет проверка на :error. И если опять нет, то мы в любом случае войдем в третий вариант метода. Нижнее подчеркивание обозначает «любые данные», а также то, что пришедшие данные нас не интересуют, то есть мы их не будем использовать. Если бы function_1(params, _) стояла первой в списке, то программа всегда выбирала бы её, и остальные два метода не работали бы никогда. Если не будет найден нужный паттерн, то вылезет исключение.

2. Pipeline

Это конструкции следующего вида:

param_1
|> func_1()
|> func_2(param_2)
…

С первого взгляда кажется фигня какая-то. Но стоит вспомнить о том, что Elixir – функциональный язык. И в функциональном языке вполне нормально делать вычисления функции от функции, без промежуточных переменных. Пайплайн – всего лишь удобная запись. Сам язык просит для ясности начинать пайплайн с переменной или значения.

Пример выше можно переписать следующим образом:

func_2(func_1(param_1), param_2)

Иначе говоря, пайплайн перенаправляет результат вычисления предыдущей функции в следующую функцию первым аргументом.

3. Отсутствие циклов

В Эликсире нет циклов. Этот факт вызвал наибольший шок у меня, и он наиболее сложен для понимания. Далее идет мое мнение и видение, которое может не совпадать с реальностью и теорией.

Корни этого факта в функциональной парадигме программирования, одно из положений которой гласит, что результат работы программы – это работа функции, которая может вызывать другие функции и программа не предполагает хранение промежуточных состояний. Циклы, в свою очередь предназначены, для многократного изменения внешнего по отношению к циклу состояния.

Заменой циклам служат 2 вещи – рекурсия и библиотечные методы работы с enumerable элементами языка.

Немного ещё о мелочах.

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

2. Атомы. В Элексире есть такое понятие как атом. Атом по сути это нечто вроде «метки». Проще всего к ним относится как к особым строкам. В примерах этой статьи уже было два атома: :ok, :error. Благодаря атомам намного проще осуществлять сопоставление паттернов, и сложные логические конструкции. По сути это константы, у которых значением является их имя. Атом всегда имеет «:» перед именем.

3. Как правильно читать заголовки методов. В Elixir принято обозначать методы следующим образом (особенно часто это видно в документации): &function/2. Читается это как метод с именем «function» и арностью 2. Арность – количество принимаемых аргументов.

Что мне помогло влиться в язык.

Во-первых, это справочник на андройде «Elixir Tutorial». Он хорош тем, что кратко охватывает основные моменты языка и его синтаксиса, и его можно почитать в автобусе. Минус: он на английском, так что подойдет не каждому.

Во-вторых, книга «Введение в Elixir» за авторством Сенлорен С., Эйзенберг Д… В данной книге показывают приемы работы с языком и объясняют их. Легко читается и позволяет значительно улучшить свою работу с языком. Также её можно найти на русском языке.

В-третьих, официальная онлайн документация. Она сделана удобно и позволяет быстро находить нужные разделы/методы, с подробным описанием и примерами.

На этом все.

Список приведенных материалов:

1. Elixir Tutorial

2. Сенлорен С., Эйзенберг Д. Введение в Elixir. Введение в функциональное программирование. – O'Reilly, 2017.

3. Официальная документация.




К сожалению, не доступен сервер mySQL