View Source merlin_quote_transform (merlin v2.1.0)
Extends merl
to allow patterns with ?Q/1
macro arbitrarily nested, as well as use those patterns directly in function heads.
It works by transforming the function clauses to a case
, which then merl
turns into a call to merl:switch/2
. This allows you to use the power of merl
matching much more conveniently.
func
: func(enter, ?Q("_@var"), #{module := State}) ->
success.
It becomes something like: func(__Arg1, __Arg2, __Arg3) ->
case merlin_quote_transform:switch(
[__Arg1, __Arg2, __Arg3],
[
fun (enter, __Var1__, #{module := State}) ->
case __Var1__ of
?Q("_@var") ->
{ok, success;
_ ->
continue
end
(_, _, _) ->
continue
end
]
) of
{ok, __ValueVar1} -> __ValueVar1;
_ ->
error(function_clause)
end.
Which then merl expands to match ?Q("_@Var") on `__Arg2
/__Var2__
.
case Foo of
#state{form=?Q("_@Var = _@Expr") = Form, bindings=Bindings} when
erl_syntax:type(Var) =:= variable
->
erl_eval:expr(Form, Bindings);
#state{form=Form} = State when
erl_syntax:type(Form) =:= variable
->
matches;
#state{} = State ->
State
end
case merlin_quote_transform:switch(
[Foo],
[
fun (#state{form=Form, bindings=Bindings}) ->
case Form of
?Q("_@Var = _@Expr") when
erl_syntax:type(Var) =:= variable
->
erl_eval:expr(Form, Bindings);
_ ->
continue
end;
(_) ->
continue
end,
fun (#state{form=Form}) ->
case
try
erl_syntax:type(Form) =:= variable
catch _:_ ->
false
end
of
true ->
matches;
false ->
continue
end;
(_) ->
continue
end,
fun (#state{} = State) ->
State;
(_) ->
continue
end
]
) of
{ok, __ValueVar1} -> __ValueVar1;
_ ->
error(function_clause)
end
Here you can see that we allow extended guards even if the clause does not have any merl patterns. But we can't just use it as it, so we wrap it in a try
/catch
.
You might also have noticed that each clause becomes its own fun
expression. This is to allow matching in stages, first vanilla Erlang and then merl, while at the same time avoiding unsafe use of variables between clauses.
Link to this section Summary
Link to this section Functions
See also: erl_anno:anno(), erl_syntax:copy_attrs/2.