使用elixir的__using__
宏并借助__on_definition__
我可以跟踪模块中的所有方法。我想要做的是用一些其他实现替换模块中的所有方法。现在创建我想要的新方法相当简单,但我也想删除现有的方法。
除此之外,有没有办法将宏应用于多个模块,而无需向每个模块明确添加use XXX
。换句话说,如果我有文件夹结构:
我可以动态地将using
宏应用于./foo/bar/
中的所有内容。
为了简化我的问题,想象一下,对于foo/bar/
文件夹中所有模块中的所有方法,我想更改那里的实现,以便它们首先运行IO.inspect "called before method"
,也就是某种方法之前的aop。
答案 0 :(得分:1)
def
只是来自Kernel
的宏。因此,您可以使用import Kernel, except: [def: 2]
将其排除,然后创建def
。除了返回值之外,这里几乎可以工作。
defmodule Def do
import Kernel, except: [def: 2]
defmacro __using__(_) do
quote do
import Kernel, except: [def: 2]
end
end
defmacro def(call, expr) do
# caller = __CALLER__
# IO.inspect call
# IO.inspect expr
# import Kernel
quote do
Kernel.def unquote(call) do
IO.puts "do something first"
unquote(expr)
end
end
end
end
defmodule Special do
use Def
import Def
def test(one, two) do
IO.puts "one: #{inspect one}, two: #{inspect two}"
end
end
在iex中运行
Interactive Elixir (1.4.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Special.test 1, 2
do something first
one: 1, two: 2
[do: :ok]
iex(2)>
我在自定义def
宏的顶部留下了一些print语句。您可以使用它来检查新def
宏的输入的AST。
您可以在Kernel源代码中找到更多信息。
我没有想过一次将use
自动应用于多个模块的想法。如果我想到任何事情,我会回来更新。