所以我正在使用Phoenix 1.3,我创建了一个宏来生成一个函数并将其注入控制器。
根据我传入的数字,我希望它生成一个包含许多参数的地图,这些参数名为“id1”,“id2”等,一直到“id#{number}”。这张地图将与通常的凤凰城“conn”一起成为参数列表的一部分。
所以我想生成一个这样的方法来进行模式匹配,并且可以执行“some stuff”:
def index(conn, %{"id1" => id1, "id2" => id2}) do
# some stuff
end
当我调用宏create_some_function_by_number("index", 2)
时。
我的宏看起来像:
defmacro create_some_function_by_number(name, num) do
params =
for n <- 1..num, do: %{"id#{n}" => Macro.var(:"id#{n}", nil)}
|> Map.new
quote do
def unquote(:"#{name}")(unquote(Macro.escape(params)) do
# some code here for the index action
end
end
end
1)如何将“conn”注入到功能头中,以便与模式匹配?
2)这是创建与图案匹配的地图的正确方法吗?
答案 0 :(得分:2)
虽然你绝对可以以这种方式使用宏,但你可能不应该这样做。这是一个有评论的工作解决方案:
defmodule MyMacro do
defmacro create_some_function_by_number(name, num, do: block) do
params =
for n <- 1..num do
{"id#{n}", Macro.var(:"id#{n}", nil)}
end
# We can't call Macro.escape because it is for escaping values.
# In this case, we have a mixture of values "id#{n}" and
# expressions "Macro.var(...)", so we build the map AST by hand.
pattern =
{:%{}, [], params}
conn =
Macro.var(:conn, nil)
quote do
def unquote(:"#{name}")(unquote(conn), unquote(pattern)) do
unquote(block)
end
end
end
end
defmodule MyExample do
import MyMacro
create_some_function_by_number :index, 2 do
{conn, id1 + id2}
end
end
IO.inspect MyExample.index(:conn, %{"id1" => 1, "id2" => 2})
正如您所看到的,宏可以使代码更难理解。如果你可以在运行时解决它,那肯定是首选。