Elixir:使用语句中的动态参数
Elixir: dynamic parameter in use statement
如何将 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
Macro.expand/2
个参数在 __CALLER__
上下文中。)
原因是宏接收 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
。
如何将 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
Macro.expand/2
个参数在 __CALLER__
上下文中。)
原因是宏接收 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
。