Macros 如何使用映射参数动态生成Phoenix控制器函数?
所以我使用Phoenix 1.3,我创建了一个宏来生成一个函数并将其注入控制器 根据我传入的数字,我希望它生成一个包含许多参数的映射,这些参数被命名为“id1”、“id2”等等,一直到“id#{number}”。此映射将与常见的Phoenix“conn”一起作为参数列表的一部分 所以我想生成一个这样的方法来匹配模式,并且可以执行“一些东西”:Macros 如何使用映射参数动态生成Phoenix控制器函数?,macros,elixir,phoenix-framework,Macros,Elixir,Phoenix Framework,所以我使用Phoenix 1.3,我创建了一个宏来生成一个函数并将其注入控制器 根据我传入的数字,我希望它生成一个包含许多参数的映射,这些参数被命名为“id1”、“id2”等等,一直到“id#{number}”。此映射将与常见的Phoenix“conn”一起作为参数列表的一部分 所以我想生成一个这样的方法来匹配模式,并且可以执行“一些东西”: def index(conn, %{"id1" => id1, "id2" => id2}) do # some stuff end 当
def index(conn, %{"id1" => id1, "id2" => id2}) do
# some stuff
end
当我调用宏create\u some\u function\u by\u 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
defmacro创建一些函数
params=
对于n Macro.var(:“id{n}”,nil)}
|>新地图
引述
def unquote(:“#{name}”)(unquote(Macro.escape(params))do
#这里有一些索引操作的代码
结束
结束
结束
1) 我如何将“conn”注入函数头,以便它可以与模式匹配
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})
defmodule MyMacro do
defmacro创建一些函数
params=
对于n来说,虽然您肯定可以用这种方式使用宏,但您可能不应该这样做。以下是一个带有注释的工作解决方案:
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})
defmodule MyMacro do
defmacro创建一些函数
params=
对于n,使用宏听起来像是过早优化。你能通过在params映射中迭代元组来解决你的问题吗?@J.RandomCoder-你有关于“在params映射中迭代元组”的链接、片段或进一步的细节吗?另外,我还想了解更多关于元编程的知识,所以我想知道这个问题的答案?我的意思是,您可以在运行时动态地响应映射中的“项”(元组)数量,而不是在编译时为任何有意义的参数定义函数。无论第一个参数中有多少个元组,下面的代码段都可以工作:Enum.map(%%{“id1”:23,“id2”:42},fn{key,value}->IO.put(“{key}:{value}”)end)
。我希望在函数头上进行精确的模式匹配,因为这似乎也能让我更轻松地利用操作回退进行错误处理。因此,如果它不匹配def some_dynamic_fund(conn,%%“id1”=>id1,“id2”=>id2}=params),请执行:“hello”
,那么它自然会返回错误。使用宏听起来像是过早优化。你能通过在params映射中迭代元组来解决你的问题吗?@J.RandomCoder-你有关于“在params映射中迭代元组”的链接、片段或进一步的细节吗?另外,我还想了解更多关于元编程的知识,所以我想知道这个问题的答案?我的意思是,您可以在运行时动态地响应映射中的“项”(元组)数量,而不是在编译时为任何有意义的参数定义函数。无论第一个参数中有多少个元组,下面的代码段都可以工作:Enum.map(%%{“id1”:23,“id2”:42},fn{key,value}->IO.put(“{key}:{value}”)end)
。我希望在函数头上进行精确的模式匹配,因为这似乎也能让我更轻松地利用操作回退进行错误处理。因此,如果它不匹配def some_dynamic_fund(conn,%%{“id1”=>id1,“id2”=>id2}=params),请执行:“hello”
,那么它自然会返回错误。