2016-02-04 3 views
10

Elixir был моим языком goto в течение последних 18 месяцев или около того, однако иногда я нахожу, что существует напряженность между мантрами «no magic» (особенно цитируется со ссылкой на Phoenix vs Rails) и использованием макросов.Есть ли простой способ увидеть, к чему расширяется макрос эликсиров?

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

Есть ли простой способ расширения макросов и просмотра кода, который они генерируют (возможно, через IEx), так что мне не нужно прорывать слои defmacro, пытаясь скомпоновать его в моей голове.

ответ

10

Вы можете расширить макрос с Macro.expand/2

iex> Macro.expand((quote do: (if true, do: 1)), __ENV__) 
{:case, [optimize_boolean: true], 
[true, 
    [do: [{:->, [], 
    [[{:when, [], 
     [{:x, [counter: 6], Kernel}, 
     {:in, [context: Kernel, import: Kernel], 
      [{:x, [counter: 6], Kernel}, [false, nil]]}]}], nil]}, 
    {:->, [], [[{:_, [], Kernel}], 1]}]]]} 

Вы можете использовать Macro.to_string/2, чтобы получить выход в виде строки вместо AST:

iex> Macro.expand((quote do: (if true, do: 1)), __ENV__) |> Macro.to_string() 
"case(true) do\n x when x in [false, nil] ->\n nil\n _ ->\n 1\nend" 

Вы можете использовать IO.puts/2 для печати строка к терминалу:

iex> Macro.expand((quote do: (if true, do: 1)), __ENV__) |> Macro.to_string() |> IO.puts() 
case(true) do 
    x when x in [false, nil] -> 
    nil 
    _ -> 
    1 
end 
5

Попробуйте этот трюк у Криса МакКорда:

your_ast |> Macro.expand(__ENV__) |> Macro.to_string |> IO.puts