Макросы являются одной из самых продвинутых и мощных функций Elixir. Как и со всеми расширенными функциями любого языка, макросы следует использовать с осторожностью. Они позволяют выполнять мощные преобразования кода во время компиляции. Теперь мы поймем, что такое макросы и как их использовать вкратце.
котировка
Прежде чем мы начнем говорить о макросах, давайте сначала посмотрим на внутренности Elixir. Программа Elixir может быть представлена своими собственными структурами данных. Строительным блоком программы Elixir является кортеж из трех элементов. Например, сумма вызова функции (1, 2, 3) представлена внутри как —
{:sum, [], [1, 2, 3]}
Первый элемент — это имя функции, второй — список ключевых слов, содержащий метаданные, а третий — список аргументов. Вы можете получить это как вывод в оболочке iex, если напишите следующее:
quote do: sum(1, 2, 3)
Операторы также представлены в виде таких кортежей. Переменные также представлены с использованием таких триплетов, за исключением того, что последний элемент является атомом, а не списком. При цитировании более сложных выражений мы можем видеть, что код представлен в таких кортежах, которые часто вкладываются друг в друга в структуру, напоминающую дерево. Многие языки называют такие представления абстрактным синтаксическим деревом (AST) . Эликсир называет эти цитируемые выражения.
закрывать кавычки
Теперь, когда мы можем получить внутреннюю структуру нашего кода, как мы можем его изменить? Чтобы ввести новый код или значения, мы используем кавычки . Когда мы цитируем выражение, оно будет оценено и введено в 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, чтобы выполнить его в своем контексте. Этот пример показывает нам метапрограммирование с использованием макросов в эликсире.
Макросы могут использоваться в гораздо более сложных задачах, но их следует использовать с осторожностью. Это связано с тем, что метапрограммирование в целом считается плохой практикой и должно использоваться только при необходимости.