Using unquote outside of quote block

Because defmodule does not call Macro.escape(..., unquote: true) and therefor unquote fragments are not supported. The reason is because unquote fragments are not needed for defmodule since the body of the module is evaluated when the surrounding code is evaluated, unlike functions where the body is evaluated only after the module is compiled.

You don’t need unquote fragments because this works:

iex(1)> x = 21
21
iex(2)> defmodule Foo do x + x end
{:module, Foo,
 <<70, 79, 82, 49, 0, 0, 3, 200, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 94,
   131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115,
   95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...>>, 42}
4 Likes

What about this kind of use case?
the code doesn’t work because the x in m(x) is {:x, [line: 17], nil} not :a, :b and :c

defmodule M do
  defmacro m(x) do
    IO.inspect x

    quote do
      @spec unquote(x)() :: atom
      def unquote(x)() do
        unquote(x)
      end
    end
  end
end

defmodule T do
  import M
  for x <- ~w(a b c)a do
    m(x)
  end
end

is there any way I can make this work?

I don’t think you need a macro here. Is this what you’re after?

defmodule M do
  def m(x) do
    quote do
      @spec unquote(x)() :: atom
      def unquote(x)() do
        unquote(x)
      end
    end
  end
end

defmodule T do
  import M
  for x <- ~w(a b c)a do
    m(x)
  end
  |> Code.eval_quoted([], __ENV__)
end
1 Like

This is great :slight_smile: thanks a lot. Code.eval_quoted is exactly the piece I was looking for. (i.e. how can I simply get this quoted piece into the module??? yay! :tada:)

this is the use case, in case anyone is interested.
autogenerated functions and typespecs.


https://hexdocs.pm/cookie_jar/CookieJar.HTTPoison.html#delete/4

1 Like

Sorry to revive this discussion. Wanted to point out that you could use unquote instead of Code.eval_quoted like:

defmodule M do
  defmacro m(x) do
    IO.inspect x

    quote do
      @spec unquote(x)() :: atom
      def unquote(x)() do
        unquote(x)
      end
    end
  end
end

defmodule T do
  import M
  for x <- ~w(a b c)a do
    m(unquote(x))
  end
end
1 Like