有时我们在修改程序的时候只是希望给旧的函数添加一个参数,我们可以使用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
来创造新的变量名
我们可以在宏的实现里面根据场景做更多有趣的事情,这里就留给大家探索吧。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。