sheharyarn

sheharyarn

Define functions in module metaprogrammically

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

Most Liked

alxndr

alxndr

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
vic

vic

Asdf Core Team

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.

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

Last Post!

sheharyarn

sheharyarn

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

http://stackoverflow.com/a/40250462/1533054

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New

Other popular topics Top

Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54996 245
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44167 214
New

We're in Beta

About us Mission Statement