Elixir在过去18个月左右一直是我的goto语言,但是我有时会发现“没有魔法”的口头禅(特别是参考Phoenix vs Rails引用)和宏的使用之间存在紧张关系。
虽然当我使用没有它们的语言时我现在想念宏,但我仍然希望看到它们实际上在做什么更容易。我的某些部分总是希望拉回DSL幕布并查看真实的代码。
有没有一种简单的方法来扩展宏并查看它们生成的代码(也许通过IEx),这样我就不必深入研究defmacro层,试图将它拼凑在一起。
Elixir在过去18个月左右一直是我的goto语言,但是我有时会发现“没有魔法”的口头禅(特别是参考Phoenix vs Rails引用)和宏的使用之间存在紧张关系。
虽然当我使用没有它们的语言时我现在想念宏,但我仍然希望看到它们实际上在做什么更容易。我的某些部分总是希望拉回DSL幕布并查看真实的代码。
有没有一种简单的方法来扩展宏并查看它们生成的代码(也许通过IEx),这样我就不必深入研究defmacro层,试图将它拼凑在一起。
您可以使用扩展宏 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
尝试克里斯麦考德的这个技巧:
your_ast |> Macro.expand(__ENV__) |> Macro.to_string |> IO.puts