我的模块中有三个相同的方法,它们(几乎)完全相同。我没有重复函数定义,而是尝试定义它们一次以保持代码最小化并且对所有函数定义相同。
到目前为止,我已尝试使用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)
我认为引用/取消引用可能是要走的路,但我不确定如何使用它们(我已经阅读了Elixir网站上的Meta Guide)。
答案 0 :(得分:1)
这样的东西?
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