Эликсир - Макросы
Макросы - одна из самых продвинутых и мощных функций Elixir. Как и все дополнительные функции любого языка, макросы следует использовать с осторожностью. Они позволяют выполнять мощные преобразования кода во время компиляции. Теперь мы вкратце разберемся, что такое макросы и как их использовать.
Цитата
Прежде чем мы начнем говорить о макросах, давайте сначала посмотрим на внутреннее устройство Elixir. Программа на Эликсире может быть представлена собственными структурами данных. Строительный блок программы на Эликсире - это кортеж из трех элементов. Например, сумма вызова функции (1, 2, 3) внутренне представлена как -
{:sum, [], [1, 2, 3]}
Первый элемент - это имя функции, второй - это список ключевых слов, содержащий метаданные, а третий - это список аргументов. Вы можете получить это как результат в оболочке iex, если напишете следующее:
quote do: sum(1, 2, 3)
Операторы также представлены такими кортежами. Переменные также представлены с использованием таких триплетов, за исключением того, что последний элемент представляет собой атом, а не список. При цитировании более сложных выражений мы видим, что код представлен такими кортежами, которые часто вложены друг в друга в структуру, напоминающую дерево. Многие языки назвали бы такие представленияAbstract Syntax Tree (AST). Эликсир называет эти цитируемые выражения.
Отменить цитату
Теперь, когда мы можем получить внутреннюю структуру нашего кода, как нам ее изменить? Чтобы ввести новый код или значения, мы используемunquote. Когда мы отменяем кавычки для выражения, оно будет оценено и введено в AST. Давайте рассмотрим пример (в оболочке iex), чтобы понять концепцию -
num = 25
quote do: sum(15, num)
quote do: sum(15, unquote(num))
Когда вышеуказанная программа запускается, она дает следующий результат -
{:sum, [], [15, {:num, [], Elixir}]}
{:sum, [], [15, 25]}
В примере для выражения кавычек оно не заменяет автоматически num на 25. Нам нужно убрать кавычки с этой переменной, если мы хотим изменить AST.
Макросы
Итак, теперь, когда мы знакомы с цитированием и отменой цитирования, мы можем изучить метапрограммирование в Elixir с помощью макросов.
Проще говоря, макросы - это специальные функции, предназначенные для возврата выражения в кавычках, которое будет вставлено в код нашего приложения. Представьте, что макрос заменяется выражением в кавычках, а не вызывается как функция. Благодаря макросам у нас есть все необходимое для расширения Elixir и динамического добавления кода в наши приложения.
Реализуем разве как макрос. Мы начнем с определения макроса с помощьюdefmacroмакрос. Помните, что наш макрос должен возвращать выражение в кавычках.
defmodule OurMacro do
defmacro unless(expr, do: block) do
quote do
if !unquote(expr), do: unquote(block)
end
end
end
require OurMacro
OurMacro.unless true, do: IO.puts "True Expression"
OurMacro.unless false, do: IO.puts "False expression"
Когда вышеуказанная программа запускается, она дает следующий результат -
False expression
То , что происходит здесь наш код заменяется приведённым кодом возвращаемого исключения случаев , когда макрос. Мы не заключили в кавычки выражение, чтобы оценить его в текущем контексте, а также не заключили в кавычки блок do, чтобы выполнить его в своем контексте. Этот пример показывает нам метапрограммирование с использованием макросов в эликсире.
Макросы можно использовать в гораздо более сложных задачах, но их следует использовать с осторожностью. Это связано с тем, что метапрограммирование в целом считается плохой практикой и должно использоваться только при необходимости.