Elixir - 通过元编程在模块中定义函数
Elixir - Define functions in module by metaprogramming
我的模块中有三个相同的方法,它们(几乎)做同样的事情。我没有重复函数定义,而是尝试将它们定义一次以保持代码最少且对所有函数都相同。
到目前为止,我已经尝试使用 Code.eval_string
:
defmodule MyModule do
Enum.each ~w(method1 method2 method3), fn method ->
@method method
Code.eval_string """
def #{@method}(map) when is_map(map) do
do_map_stuff(:#{@method}, map)
end
def #{@method}(arg) do
do_other_stuff(:#{@method}, arg)
end
"""
end
## Other Methods
end
但这会抛出 ArgumentError
:
Compiling 1 file (.ex)
** (ArgumentError) cannot invoke def/2 outside module
(elixir) lib/kernel.ex:4297: Kernel.assert_module_scope/3
(elixir) lib/kernel.ex:3299: Kernel.define/4
(elixir) expanding macro: Kernel.def/2
nofile:1: (file)
我认为 quote/unquote 可能是可行的方法,但我不确定如何使用它们(我已经阅读了 Elixir 网站上的 Meta Guide)。
是这样的吗?
defmodule MyModule do
def do_map_stuff(method, arg) do
IO.inspect([method, arg])
end
Enum.each [:method1, :method2, :method3], fn method ->
def unquote(method)(map) when is_map(map) do
do_map_stuff(unquote(method), map)
end
def unquote(method)(arg) do
do_map_stuff(unquote(method), arg)
end
end
end
我的模块中有三个相同的方法,它们(几乎)做同样的事情。我没有重复函数定义,而是尝试将它们定义一次以保持代码最少且对所有函数都相同。
到目前为止,我已经尝试使用 Code.eval_string
:
defmodule MyModule do
Enum.each ~w(method1 method2 method3), fn method ->
@method method
Code.eval_string """
def #{@method}(map) when is_map(map) do
do_map_stuff(:#{@method}, map)
end
def #{@method}(arg) do
do_other_stuff(:#{@method}, arg)
end
"""
end
## Other Methods
end
但这会抛出 ArgumentError
:
Compiling 1 file (.ex)
** (ArgumentError) cannot invoke def/2 outside module
(elixir) lib/kernel.ex:4297: Kernel.assert_module_scope/3
(elixir) lib/kernel.ex:3299: Kernel.define/4
(elixir) expanding macro: Kernel.def/2
nofile:1: (file)
我认为 quote/unquote 可能是可行的方法,但我不确定如何使用它们(我已经阅读了 Elixir 网站上的 Meta Guide)。
是这样的吗?
defmodule MyModule do
def do_map_stuff(method, arg) do
IO.inspect([method, arg])
end
Enum.each [:method1, :method2, :method3], fn method ->
def unquote(method)(map) when is_map(map) do
do_map_stuff(unquote(method), map)
end
def unquote(method)(arg) do
do_map_stuff(unquote(method), arg)
end
end
end