# Define functions in module metaprogrammically

**URL:** <https://forum.elixirforum.com/t/define-functions-in-module-metaprogrammically/2122>\
**Category:** Questions\
**Tags:** metaprogramming\
**Created:** [October 25, 2016, 9:56pm UTC](https://forum.elixirforum.com/t/define-functions-in-module-metaprogrammically/2122 "2016-10-25T21:56:14Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![sheharyarn](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sheharyarn/32/23945_2.png) [@sheharyarn](https://forum.elixirforum.com/u/sheharyarn)\
**Post date:** [October 25, 2016, 9:56pm UTC](https://forum.elixirforum.com/t/define-functions-in-module-metaprogrammically/2122/1 "2016-10-25T21:56:14Z")

</div>

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](http://elixir-lang.org/getting-started/meta/quote-and-unquote.html) on the Elixir website).

---

<div class="post-metadata">

**Author:** ![alxndr](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/alxndr/32/236_2.png) [@alxndr](https://forum.elixirforum.com/u/alxndr)\
**Post date:** [October 25, 2016, 10:08pm UTC](https://forum.elixirforum.com/t/define-functions-in-module-metaprogrammically/2122/2 "2016-10-25T22:08:52Z")

</div>

Don’t need to use `Code.eval_string`; you can wrap a `def` in a “loop” and use `unquote/1` to “extract” the variable into the context that you’re `def`-ing in:

```
defmodule M do
  Enum.each ~w(foo bar), fn(method_name) ->
    def unquote(:"#{method_name}")(), do: unquote(method_name)
  end
end

```

---

<div class="post-metadata">

**Author:** ![vic](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/vic/32/11426_2.png) [@vic](https://forum.elixirforum.com/u/vic)\
**Post date:** [October 25, 2016, 10:10pm UTC](https://forum.elixirforum.com/t/define-functions-in-module-metaprogrammically/2122/3 "2016-10-25T22:10:31Z")

</div>

There’s no need to use eval\_string, you could use `Code.eval_quoted` but it’d be much much better to just define a macro in another module and then import it.

Here’s a quick example, you can put on a file `foo.ex` and execute with elixir.

```elixir
defmodule Gen do

  # Note that macro arguments and return values are quoted expressions
  defmacro gen({name, _, _}) do
    quote do

      # here we define it dinamically
      def unquote(name)() do
        IO.inspect(unquote(name))
      end

    end
  end
end

defmodule Foo do
  import Gen
  gen foo
end

Foo.foo

```

---

<div class="post-metadata">

**Author:** ![sheharyarn](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/sheharyarn/32/23945_2.png) [@sheharyarn](https://forum.elixirforum.com/u/sheharyarn)\
**Post date:** [October 25, 2016, 10:14pm UTC](https://forum.elixirforum.com/t/define-functions-in-module-metaprogrammically/2122/4 "2016-10-25T22:14:31Z")

</div>

Thank you. Someone just posted this as an answer on my SO question as well.

[http://stackoverflow.com/a/40250462/1533054](http://stackoverflow.com/a/40250462/1533054)
