有时咱们在批改程序的时候只是心愿给旧的函数增加一个参数,咱们能够应用macro来简化这一流程。
这里是一个简略的例子,咱们应用了一个名为 define
的宏,它的作用是增加一个名为 state
的参数到函数里。
defmodule M3 do use M2, head: :state define f(:a, a) define f(:b, b) define g(a, c)end
iex(1)> h M3.f def f(state, atom, a)
define
宏的实现是这样的:
defmodule M2 do defmacro __using__(opts) do head = opts[:head] Module.put_attribute(__CALLER__.module, :__head__, head) quote do import M2 end end defmacro define(call) do case Macro.decompose_call(call) do {f, a} -> mod = __CALLER__.module var = Module.get_attribute(mod, :__head__) |> Macro.var(nil) args = [var | a] quote do def unquote(f)(unquote_splicing(args)) do IO.puts("args: #{inspect(unquote(args))}") end end _ -> raise "invalid args" end endend
次要的几个点:
- 用
use
来传入咱们设定的新参数的名字 - 用模块属性来保留新参数的名字
- 用
__CALLER__.module
来获取宏执行时所在的模块 - 用
Macro.decompose_call
来解构macro接管到的函数调用 - 用
unquote_splicing
来将 list 还原成参数(拆解list) - 用
Macro.var
来发明新的变量名
咱们能够在宏的实现外面依据场景做更多乏味的事件,这里就留给大家摸索吧。