Why this does not work, but the one you gave work.
defmacro rule({ name, goal, work }) do
quote do
def unquote(name)({ unquote(Macro.escape(goal)), unquote(Macro.escape(work)) }), do: true
end
end
ProdSys.rule({ :test, %{ goal: “test” }, %{} })
** (ArgumentError) cannot invoke def/2 outside module
(elixir) lib/kernel.ex:5122: Kernel.assert_module_scope/3
(elixir) lib/kernel.ex:3893: Kernel.define/4
(elixir) expanding macro: Kernel.def/2
iex:24: (file)
(prod_sys) expanding macro: ProdSys.rule/1
iex:24: (file)
iex(28)> expr = quote do: ProdSys.rule({ :test, %{ goal: "test" }, %{} })
{{:., [], [{:__aliases__, [alias: false], [:ProdSys]}, :rule]}, [],
[{:{}, [], [:test, {:%{}, [], [goal: "test"]}, {:%{}, [], []}]}]}
iex(29)> res = Macro.expand_once(expr, __ENV__)
{:def, [context: ProdSys, import: Kernel],
[
{:{}, [context: ProdSys],
[
{[],
[:test, {:{}, [], [:%{}, [], [goal: "test"]]}, {:{}, [], [:%{}, [], []]}]}
]},
[do: true]
]}
iex(30)> IO.puts Macro.to_string(res)
def({{[], [:test, {:%{}, [], [goal: "test"]}, {:%{}, [], []}]}}) do
true
end
:ok