Hi,
I am trying to define a macro with 3 arguments (name, var, body)
which is to generate function name/1
a) with argument var
, possibly arbitrary complex pattern-matching expression
b) besides var
, other variables bound in the outer scope can be used in the body
Example:
defmodule Mac3Use do
import Mac3
for {g, v} <- [g1: 1, g2: 2] do
gen String.to_atom("#{g}_x"), a, do: {:ok, 1, a}
gen String.to_atom("#{g}_y"), %{y: y} = a, do: {:ok, y, a}
# gen String.to_atom("#{g}_z"), a, do: {:ok, v, a} # undefined function v/0
end
end
Below the implementation satisfying a). With slight modification it can handle guards. Unfortunately it doesnât handle b) - I get âundefined function v/0â CompileError.
defmodule Mac3 do
defmacro gen(name, var \\ quote(do: _), do: block) do
var = Macro.escape(var)
block = Macro.escape(block)
quote bind_quoted: [name: name, var: var, block: block] do
def unquote(name)(unquote(var)) do
unquote(block)
end
end
end
end
I was trying to modify this code without luck. Inspect of binding() inside quote
shows g
and v
variables from the example with proper values bound, but unquote(block)
doesnât want to consume v
.
Just a moment ago I checked that
@v v
gen String.to_atom("#{g}_z"), a, do: {:ok, @v, a}
works, but itâs rather a hack.
As you could notice, the macro resembles ExUnit.Case.test/3
, and its implementation is simplified version of that from ExUnit
.
Is there an easy solution to this?
Thank you,
Waldemar.