Elixir - Define functions in module by metaprogramming

elixir, metaprogramming

Solution

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

Problem

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).

Original source