Учебники

Эликсир — Макросы

Макросы являются одной из самых продвинутых и мощных функций 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, чтобы выполнить его в своем контексте. Этот пример показывает нам метапрограммирование с использованием макросов в эликсире.

Макросы могут использоваться в гораздо более сложных задачах, но их следует использовать с осторожностью. Это связано с тем, что метапрограммирование в целом считается плохой практикой и должно использоваться только при необходимости.