Макрос - это способ программирования языка программирования.Проще говоря, макрос - это способ генерировать программный код, а не писать его все время.
С другой стороны, языковая конструкция (иногда называемая «особой формой») - это то, что лежит в основе самого эликсира.Упрощение может заключаться в том, что реализация if
осуществляется не в Elixir, а на языке, на котором реализован Elixir.
Предположим, вы хотите использовать упомянутое unless
.
Редактировать: unless
- это , доступный в эликсире.Но давайте предположим, что это не так.
В Elixir нет unless
, доступного на языке.Хосе Валим не реализовал это.Но вы всегда можете написать что-то, что имеет ту же семантику: отрицательный if
.
Мы бы хотели бы , чтобы иметь это, но мы не :
unless sun_shines() do
open_umbrella()
end
Но у нас есть только if
и not
, поэтому мы можем написать:
if not sun_shines() do
open_umbrella()
end
Во-вторых, макрос - это особый вид функции, но его параметрыявляются кодом, и результатом выполнения макроса также является код.Предполагая, что у нас есть макрос unless
, он принимает условие (т. Е. sun_shines()
) и тело (т. Е. open_umbrella()
) и возвращает if not sun_shines(), do: open_umbrella()
.Таким образом, макрос - это функция, которая работает на уровне вашего «мертвого кода» и генерирует «мертвый код».
Вы можете подумать, что это слишком глупо, чтобы писать макрос для.Это правда.Но такого рода проблемы случаются чаще, чем вы думаете, и тогда макрос является отличным решением этой проблемы.Это просто способ программирования вашего языка программирования.
Пример реализации макроса unless
был предоставлен Алексеем Матюшкиным:
defmodule MyMacros do
defmacro unless(ast, do: block) do
quote do
if not unquote(ast) do
unquote(block)
end
end
end
end
Здесь вы можете ясно видеть, что вы даете ему AST (Абстрактное синтаксическое дерево), и этопреобразует его в другой AST (quote
) и вставляет его в то место, где вы вызвали макрос.Обратите внимание, что все это происходит во время компиляции.Ваша программа в данный момент не выполняется!
Например, предположим, что у вас есть вышеуказанный модуль, и это ваша программа:
defmodule MyProgram do
def my_function(x) do
unless sun_shining() do
open_umbrella()
end
end
end
После компиляции и перед выполнением вашПрограмма будет выглядеть так:
defmodule MyProgram do
def my_function(x) do
if not sun_shining() do
open_umbrella()
end
end
end
Эта фаза называется фазой расширения макроса.
Кроме того, здесь вы можете найти два фактических макроса, используемых в Elixir и ExUnit соответственно.
https://github.com/elixir-lang/elixir/blob/d48b16cf549eca0629449a47cc5574a7170706c3/lib/ex_unit/lib/ex_unit/assertions.ex#L104
https://github.com/elixir-lang/elixir/blob/13ced80fcda1bea69037aacd4b052a0c44b4be61/lib/elixir/lib/stream/reducers.ex#L58
Примечание:Я продолжаю добавлять все больше и больше информации к этому ответу.Ответ на самом деле заслуживает целой книги, и Эликсир метапрограммирования от Крис МакКорд является лучшим.