amalbuquerque

amalbuquerque

Clear definition of unquote fragments

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!

Most Liked

kip

kip

ex_cldr Core Team

I think this post has a good summary: Using unquote outside of quote block

amalbuquerque

amalbuquerque

Hi @kip, thanks for the reply. I’ve mentioned that post on my initial message. I understand why we can do it, it may seem at first glance there’s no quote block wrapping the unquote call, but there is one in fact due to the macro arguments being quoted for us.

What I didn’t understand and think it isn’t completely clear on the documentation is the concept of unquote fragment. Saying that it is what we use to dynamically define a function IMO gives room for interpretation.

Where Next?

Popular in Questions Top

srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
gonzofish
I’m currently trying to understand how to join three tables using Ecto. All the examples I’ve seen use 2, so maybe I’m just missing somet...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

We're in Beta

About us Mission Statement