@ TGO уже дал идеальный ответ, почему __info__(:functions)
не показывает unless
;Я все еще думаю, что требуется какое-то разъяснение.
Насколько я понимаю, макрос развернут в окончательную форму AST и его не остается после его компиляции.
Это действительно очень верно. Дело в том, что Elixir компилирует все перед выполнением, и, записывая MyLogic.unless ...
, вы никоим образом не вызываете / вызываете макрос.Что происходит, вы приказываете Elixir вводить AST, возвращаемый MyLogic.unless
в ваш код вместо MyLogic.unless
, во время компиляции вашего кода .В полученном ЛУЧЕ нет никаких следов макроса.
как мне представить его в моем уме?
MyLogic.unless false, do: IO.puts("It works")
расширен точно до:
if !false, do: IO.puts("It works")
unquote
необходимо в объявлении макроса при вызове quote do
, поскольку макросы получают выражений в кавычках в качестве аргументов.Вы можете попытаться IO.inspect/2
аргументы внутри вызова макроса , вне quote do
:
defmacro unless(expr, opts) do
IO.inspect({expr, opts}, label: "compilation time!")
quote, do: if !unquote(expr), unquote(opts)
end
, как Elixir узнает, что unless
являетсяярлык к полностью расширенному макрокоду?
Есть действительно замечательное объяснение того, как Elixir поддерживает внутреннюю информацию на этапе компиляции, которую это поле слишком мало, чтобы содержать.В общем, эликсир ничего не знает .Вы должны четко различать время компиляции и время выполнения контексты.Вы говорите о казни .Это происходит после того, как все скомпилировано и ваш пользовательский MyLogic.unless/1
больше не существует, заменяется введенным AST.
Elixir не может выполнить не скомпилированный код, это не язык сценариев.Не дайте себя одурачить REPL: iex
под капотом эффективно компилирует все , которое вы «выполняете» там до реального выполнения.
, что макросв Elixir на самом деле есть функция (из ваших комментариев к другому ответу)
Это ни в коем случае не правильно.Функции существуют как код, который выполняется ErlangVM в полученном BEAM (после прохождения компиляции.) Макросы не .