elixir在宏中定义动态函数
我试图在elixir在宏中定义动态函数,elixir,Elixir,我试图在defmacro中动态定义函数,但无法理解函数值在函数本身中不可用的原因 defmacro __using__(_) do Enum.each ~w(public private), fn value -> def unquote(:"make_#{value}")(user = %User{}) do %{user | privacy: value} end end end Elixir在默认情况下将value扩展为value(),然后表示
defmacro
中动态定义函数,但无法理解函数值在函数本身中不可用的原因
defmacro __using__(_) do
Enum.each ~w(public private), fn value ->
def unquote(:"make_#{value}")(user = %User{}) do
%{user | privacy: value}
end
end
end
Elixir在默认情况下将
value
扩展为value()
,然后表示没有此类功能您在def
周围缺少引号
。您还需要在def
内的映射更新表达式中取消引用该值。最后,您需要在此处使用Enum.map
,而不是Enum.each
,以便\uuuuuuuuuuuuuuuuuuu using\uuuuu1
返回构建的AST:
defmacro __using__(_) do
Enum.map ~w(public private), fn value ->
quote do
def unquote(:"make_#{value}")(user = %User{}) do
%{user | privacy: unquote(value)}
end
end
end
end
测试:
编辑:评论中请求的更改:
defmacro __using__(_) do
Enum.map ~w(public private), fn value ->
quote do
def unquote(:"make_#{value}")(user = %User{}) do
%{user | privacy: unquote(value)}
end
def unquote(:"make_#{String.upcase(value)}")(user = %User{}) do
%{user | privacy: unquote(String.upcase(value))}
end
end
end
end
您在
def
周围缺少一个quote
。您还需要在def
内的映射更新表达式中取消引用该值。最后,您需要在此处使用Enum.map
,而不是Enum.each
,以便\uuuuuuuuuuuuuuuuuuu using\uuuuu1
返回构建的AST:
defmacro __using__(_) do
Enum.map ~w(public private), fn value ->
quote do
def unquote(:"make_#{value}")(user = %User{}) do
%{user | privacy: unquote(value)}
end
end
end
end
测试:
编辑:评论中请求的更改:
defmacro __using__(_) do
Enum.map ~w(public private), fn value ->
quote do
def unquote(:"make_#{value}")(user = %User{}) do
%{user | privacy: unquote(value)}
end
def unquote(:"make_#{String.upcase(value)}")(user = %User{}) do
%{user | privacy: unquote(String.upcase(value))}
end
end
end
end
但是如果我需要添加更多的函数到与动态生成的
def
相同的级别,该怎么办?您可以将任意数量的def
放在quote
中。问题是\u使用
函数需要一个AST定义列表,因此,如果我声明多个quote
,则只取最后一个。我不确定我是否遵循。我编辑的答案是否符合您的要求?@Dogbert一个简短的问题:使用Enum.map
返回的值是引用函数定义的列表。这将插入到调用模块中。它定义了功能吗?Quoted list是列表本身,但它是否意味着编译器执行每个元素,所以定义了函数?但是如果我需要添加更多的函数到动态生成的def
的同一级别怎么办?您可以在引号内放置任意数量的def
。问题是\u使用
函数需要一个AST定义列表,因此,如果我声明多个quote
,则只取最后一个。我不确定我是否遵循。我编辑的答案是否符合您的要求?@Dogbert一个简短的问题:使用Enum.map
返回的值是引用函数定义的列表。这将插入到调用模块中。它定义了功能吗?Quoted list是列表本身,但它是否意味着编译器执行每个元素,从而定义函数?
iex(1)> %User{} |> B.make_public
%User{privacy: "public"}
iex(2)> %User{} |> B.make_PUBLIC
%User{privacy: "PUBLIC"}
iex(3)> %User{} |> B.make_private
%User{privacy: "private"}
iex(4)> %User{} |> B.make_PRIVATE
%User{privacy: "PRIVATE"}