以编程方式访问typespec的定义

时间:2017-01-19 13:26:08

标签: reflection types elixir

我如何在代码中访问typespec的定义?我希望在宏中使用它以执行一些代码生成。

这样的事情是理想的。

鉴于此模块和typespec:

defmodule MyMod do
  @type t :: :ok | :error
end

我可以调用Code.get_type(MyMod, :t)之类的函数,它会返回定义表达式的AST:

{:::, [], [{:my_type, [], Elixir}, {:|, [], [:ok, :error]}]}

或者只是类型的AST:

{:|, [], [:ok, :error]}

1 个答案:

答案 0 :(得分:1)

这是一个黑客攻击(仅适用于编译阶段),但它可以满足您的需求:

defmodule MyMod do                                      
  @type t1 :: :ok | :error
  @type t2 :: :done
  @type_defs Module.get_attribute(__MODULE__, :type, [])
  def type_defs,
    do: Enum.map(@type_defs, fn {:type, type, _} -> type end)
end

MyMod.type_defs
#⇒ [{:::, [line: 9], [{:t2, [line: 9], nil}, :done]},
#   {:::, [line: 8], [{:t1, [line: 8], nil}, {:|, [line: 8], [:ok, :error]}]}]

有人可能会声明一个包含defmacro __using__的模块,并在需要时实现此功能和use TypeExtractor