如何将adapter
参数动态传递给Nebulex.Cache模块初始化?
defmodule MyApp.RedisCache do
use Nebulex.Cache,
otp_app: :nebulex,
adapter: if true do NebulexRedisAdapter else Nebulex.Adapters.Nil end
end
最简单的方法是将条件上移一级。
defmodule MyApp.RedisCache do
if true do
use Nebulex.Cache,
otp_app: :nebulex,
adapter: NebulexRedisAdapter
else
use Nebulex.Cache,
otp_app: :nebulex,
adapter: Nebulex.Adapters.Nil
end
...
end
另一种方法是创建一个带有参数的私有宏,或者创建一个存储adapter
的模块属性并将其传递给use
(假设Nebulex.Cache
在__CALLER__
上下文中执行Macro.expand/2
自变量)
原因是宏接收AST,所以__using__/1
将接收的是quote do: if ....
,它甚至不会在第一个编译阶段尝试编译。
下面的代码可能会揭示如何在调用之间传递AST以及Macro.expand/2
的作用。
defmodule M do
@param if(true, do: M1, else: M2)
defmacrop t1(arg: args) do
IO.inspect(args, label: "#1")
end
defmacrop t2(arg: args) do
IO.inspect(Macro.expand(args, __CALLER__), label: "#2")
end
def test do
t1(arg: if(true, do: M1, else: M2))
t2(arg: if(true, do: M1, else: M2))
t1(arg: @param)
t2(arg: @param)
end
end
结果是:
#1: {:if, [line: 19],
...
#2: {:case, [optimize_boolean: true],
...
#1: {:@, [line: 21], [{:param, [line: 21], nil}]}
#2: M1
注意,if
被扩展为case
,并且模块属性没有被扩展,除非对其调用显式Macro.expand/2