I have some relatively legitimate reasons do do something like this (even if you think this is not even remotely legitimate, the question at the end is independent from this):
defmodule MySnippet do
defmacro __using__(_) do
quote do
def common_function1() do
# ...
end
def common_function2() do
# ...
end
# etc...
end
end
end
defmodule MyModule1 do
use MySnippet
def specific_function1() do
# ...
end
def specific_function2() do
# ...
end
# etc...
end
defmodule MyModule2 do
use MySnippet
def specific_function_a() do
# ...
end
def specific_function_b() do
# ...
end
# etc...
end
I’ve thought about defining a defsnippet
macro that exapnds so that I coould do this:
require Snippet
Snippet.defsnippet MySnippet do
def f(x), do: x
def g(x), do: x
end
This way, it looks like a normal module definition and is easier to type.
I’ve written the following macro, which tries to encapsulate the module definition and the __using__/1
macro definition.
defmodule Snippet do
defmacro defsnippet(module_name, [do: body]) do
quote bind_quoted: [module_name: module_name, body: body] do
defmodule module_name do
@doc false
defmacro __using__(_opts) do
quote do
body
end
end
end
end
end
end
But when I try to run it like this
# lib/schism/example.ex
require Snippet
Snippet.defsnippet MySnippet do
def f(x), do: x
def g(x), do: x
end
I get this error:
== Compilation error in file lib/schism/example.ex ==
** (ArgumentError) cannot invoke def/2 outside module
(elixir) lib/kernel.ex:5142: Kernel.assert_module_scope/3
(elixir) lib/kernel.ex:3905: Kernel.define/4
(elixir) expanding macro: Kernel.def/2
lib/schism/example.ex:4: (file)
expanding macro: Snippet.defsnippet/2
lib/schism/example.ex:3: (file)
I don’t understand where this comes from, because I’m not calling def/2
outside of a module. I’m just taking some AST that happens to contain def
s and putting it inside a macro which I can invoke later.
Doing all of this just to save some typing is probably not worth it and I don’t know if I’ll end up going that way, but no I’m curious about what the problem is independently of the rest.