共计 812 个字符,预计需要花费 3 分钟才能阅读完成。
有时咱们在批改程序的时候只是心愿给旧的函数增加一个参数,咱们能够应用 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 | |
end | |
end |
次要的几个点:
- 用
use
来传入咱们设定的新参数的名字 - 用模块属性来保留新参数的名字
- 用
__CALLER__.module
来获取宏执行时所在的模块 - 用
Macro.decompose_call
来解构 macro 接管到的函数调用 - 用
unquote_splicing
来将 list 还原成参数(拆解 list) - 用
Macro.var
来发明新的变量名
咱们能够在宏的实现外面依据场景做更多乏味的事件,这里就留给大家摸索吧。
正文完