Reputation: 75820
I have three identical methods in my module, that do (almost) exactly the same thing. Instead of repeating the function definitions, I am trying to define them once to keep code minimal and same for all of them.
So far I've tried using 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
but this throws 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)
I think quote/unquote might be the way to go, but I'm not exactly sure how to do this using them (I've already read the Meta Guide on the Elixir website).
Upvotes: 5
Views: 1321
Reputation: 9693
Something like this?
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
Upvotes: 4