2016-02-04 10 views
10

Elixir è stato il mio linguaggio goto negli ultimi 18 mesi o giù di lì, tuttavia a volte trovo che c'è una tensione tra il mantra "no magic" (specialmente citato con riferimento a Phoenix vs Rails) e l'uso di macro.C'è un modo semplice per vedere a cosa si espande una macro di elisir?

Mentre ora mi mancano i macro quando uso lingue senza di loro, vorrei ancora che fosse più facile vedere cosa stanno effettivamente facendo. Una parte di me vuole sempre tirare indietro la tenda della DSL e vedere il codice reale.

C'è un modo semplice per espandere i macro e vedere il codice che generano, (forse tramite IEx) in modo da non dover scavare negli strati di defmacro cercando di metterlo insieme nella mia testa.

risposta

10

È possibile espandere una macro con 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]}]]]} 

È quindi possibile utilizzare Macro.to_string/2 per ottenere il risultato come una stringa invece di un 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" 

È quindi possibile utilizzare IO.puts/2 per stampare il stringa al terminale:

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

Prova questo trucco di Chris McCord:

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