Hi there,
After reading @ericmj response here (Using unquote outside of quote block) about “unquote fragments”, I still can’t completely grasp the concept.
I’ve read the documentation many times now, besides some other resources (including McCord’s Metaprogramming Elixir), and I can’t reach to a concrete definition of what an unquote fragment is.
I’ve read in some places that “unquote fragments” is the usage of unquote that lets us dynamically define functions and nested macros (https://dockyard.com/blog/2016/08/16/the-minumum-knowledge-you-need-to-start-metaprogramming-in-elixir). After reading all this, I think both unquote/1 calls on the documentation example are “unquote fragments”, since they will be injected on the caller context and won’t have an explicit quote block enclosing them. Am I right?:
defmacro defkv(kv) do
quote bind_quoted: [kv: kv] do
Enum.each kv, fn {k, v} ->
def unquote(k)(), do: unquote(v)
end
end
end
And consider this example please:
defmodule Foo do
alias Baz
fun_definition = {:bar, [], [{:arg, [], nil}]}
body = {:__block__, [], [{:*, [], [{:arg, [], nil}, {:arg, [], nil}]}]}
function = :bar
arity = 1
def(unquote(fun_definition)) do
mfa = Baz.mfa(__MODULE__, unquote(function), unquote(arity)) # returns "Module.function/arity"
Baz.run(mfa, fn -> unquote(body) end)
end
end
Here I think the unquote(fun_definition) is definitely an unquote fragment because is allowing us to dynamically define the function. But I am not so sure regarding the other unquote/1 calls for function
, arity
and body
. Since they are contributing for the dynamic definition of the function body, are they also unquote fragments?
Thanks in advance,
And thank you all for the amazing community!
lejboua
P.S.: Given the different opinions and definitions I’ve read, IMO the documentation could be updated to include an explicit unquote fragment definition. This way those like me who are starting to look at Elixir would be able to clearly distinguish between a “normal” unquote inside an explicit quote block and an unquote fragment.
P.S.2: I know that we can use the unquote/1 calls inside the def/2 macro arguments because the def/2 arguments, like any macro, are being quoted for us.
Many thanks!