1

有时我们在修改程序的时候只是希望给旧的函数添加一个参数,我们可以使用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 来创造新的变量名

我们可以在宏的实现里面根据场景做更多有趣的事情,这里就留给大家探索吧。


Ljzn
399 声望102 粉丝

网络安全;函数式编程;数字货币;人工智能