简体   繁体   中英

Is there an easy way to see what an Elixir macro expands to?

Elixir has been my goto language for the past 18 months or so, however I sometimes find there is a tension between the "no magic" mantra (especially cited with reference to Phoenix vs Rails) and the use of macros.

While I now miss macros when I'm using languages without them, I still wish it was easier to see what they are actually doing. Some part of me always wants to pull back the DSL curtain and see the real code.

Is there a simple way to expand macros and see the code they generate, (perhaps via IEx) so that I don't have to dig through the layers of defmacro trying to piece it together in my head.

You can expand a macro with 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]}]]]}

You can then use Macro.to_string/2 to get the output as a string instead of an 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"

You can then use IO.puts/2 to print the string to the terminal:

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

尝试Chris McCord的这个技巧:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM