On compilation stage I can easily produce functions with:
defmodule A1 do
defmodule A2 do
Enum.each %{m: 42}, fn {k, v} ->
def unquote(k)(), do: unquote(v)
end
end
end
IO.puts A1.A2.m
#⇒ 42
Also, I can produce modules with functions from within a function call:
defmodule B1 do
def b2! do
defmodule B2 do
# enum is for the sake of future example
Enum.each %{m1: 42}, fn {_k, v} ->
# def b2(), do: unquote(v) WON’T WORK (WHY?), BUT
@v v
def b2(), do: @v
end
end
end
end
B1.b2! # produce a nested module
IO.puts B1.B2.b2 # call a method
#⇒ 42
Now my question is: how can I dynamically produce a module with dynamically created function names, e. g.:
defmodule B1 do
def b2! do
defmodule B2 do
Enum.each %{m1: 42, m2: 3.14}, fn {k, v} ->
@k k
@v v
def unquote(@k)(), do: @v # THIS DOESN’T WORK
end
end
end
end
NB I was able to achieve what I wanted with
defmodule B1 do
def b2! do
defmodule B2 do
Enum.each %{m1: 42, m2: 3.14}, fn {k, v} ->
ast = quote do: def unquote(k)(), do: unquote(v)
Code.eval_quoted(ast, [k: k, v: v], __ENV__)
end
end
end
end
but it seems to be quite hacky.