Dynamically defining functions from __using__

This works:

defmodule Foo do
  Enum.each(["foo", "bar"], fn name ->
    def unquote(:"#{name}")() do
      unquote(name)
    end
  end)
end

But this doesn’t work…

defmodule Bar do
  defmacro __using__(_) do
    quote do
      Enum.each(["foo", "bar"], fn name ->
        def unquote(:"#{name}")() do
          unquote(name)
        end
      end)
    end
  end
end

defmodule Foo do
  use Bar
end

Why? And how to get it to work?

Thanks!

the unquote when in the module body is unquoting within the module body. IN the Bar example unquote is unquoting with respect to the wrapping quote. You need the unquote to end up in the module itself.

The bind_quoted option to quote will make sure this happens:

defmodule Bar do
  defmacro __using__(_) do
    quote bind_quoted: [] do
      Enum.each(["foo", "bar"], fn name ->
        def unquote(:"#{name}")() do
          unquote(name)
        end
      end)
    end
  end
end
3 Likes