laiboonh
This is a code snippet from the metaprogramming elixir book.
defmacro test(description, do: test_block) do
test_func = String.to_atom(description)
quote do
@tests {unquote(test_func), unquote(description)}
def unquote(test_func)(), do: unquote(test_block)
end
end
Can someone enlighten me on what is def unquote(test_func)(), do: unquote(test_block) doing? How is it even legal syntax??? I tried it out on iex:
iex(67)> defmodule Test do
...(67)> def test(a)(), do: a
...(67)> end
** (CompileError) iex:68: invalid syntax in def test(a)()
iex:68: (module)
Trending in Questions
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
Hi everyone.
My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
Hello,
I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind.
However, when I launch mix phx.server, I get an error...
New
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
Hello folks!
So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
I’m working on a small exercise involving update_in/3, and I came up with this solution:
data = %{
name: "Periodic Table",
category:...
New
How Can I Optimise Compile Time Dependencies
I have been building an elixir application for about 2 years now. Many modules and files ha...
New
Other Trending Topics
Edit: 2026 May 15 - This post is archived.
Mob is alive!!
Main docs: mob v0.7.11 — Documentation
A bit of explanation for the slightly c...
New
A little off-topic, but I feel like people here have a good head on their shoulders.
I used to be quite good at making software. Was luc...
New
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #ai
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #security
- #metaprogramming










Showing Posts 1 to 8- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
h4cc
unquoteis a function to “create code from data” simply said.When this is executed
def unquote(test_func)(), do: unquote(test_block)the result will be
def :description_as_atom(), do: [list, of, test, blocks]which will be valid code for the compiler.
Short:
unquotewill mostly be called in macros to generate code from parameters (which is data at compile time), so only the result ofunquotewill stay afterwards.Eiji
@laiboonh: Inside
quotedo_block your expressions are quoted.For example:
Similarly
test_funcanddescriptionare quoted too.Simple explanation for new developer is that
unquoteconverts quoted expressions (AST) to their “normal” form.For example:
So your line is “translated” from Elixir AST:
to “normal” code like:
You can see how it looks by inspecting variables in
quotedo_block without unquote part.Please see: Quote and unquote for more informations.
laiboonh
Hi, thanks for helping me out here. One thing i don’t understand is what actually happens in
unquote. I have modified your code slightlyLet’s not use AST literals but something else so that we can see the difference.
Example.sample(%{name: "Lai"}). This is my understanding, correct me if i’m wrong.I understand that arguments become quoted expression inside the body of a macro. Hence
abecomes{:%{}, [line: 41], [name: "Lai"]}inside the macro body.unquoteis like string interpolation hence we “substitute” inaand the macro body becomesIO.inspect quote do: {:%{}, [line: 41], [name: "Lai"]}finally when you quote some quoted expression (AST) you get back the same quoted expression and IO.inspect prints out
{:%{}, [line: 41], [name: "Lai"]}Is this how it goes? I am a bit confused by your statement.
{:%{}, [line: 41], [name: "Lai"]}or%{name: "Lai"}benwilson512
Think of
unquoteas similar to#{}in strings. If you havename = "Bob"; greeting = "hello #{name}"the contents ofnameare injected into thegreetingstring producing"hello Bob".When you do something like
you’re inserting the AST contents of
capitalize_astintoresultwhich makesresultthe AST:IO.inspect(unquote(String.capitalize("hello"))laiboonh
Actually i was just curious whether
unquotedoes a substitution or does a conversion as well like Eiji mentioned. I rationalized that its like you said a mere substitution.No matter
unquoteis unquoting an expression or a quoted expression, it will in the end result in an AST becauseunquotehas to happen within aquoteblockEiji
@laiboonh: You can think about AST like a Assembler code.
AST is a data (in tuple notation), but it could be nested instead of simple Assembler plain instructions list.
quoteis changing code to AST, so you are generating quoted code inquoteblock. You cannot access variables outside of this block unless you callunquote.You can think about quoting like about generating file using controller data. Your controller data are all variables inside your macro/function including it’s arguments. To access them instead of calling
<%= assigns.something %>you are usingunquote(something).unquotefetches raw value of variable and/or expression and puts it into quote block.Finally
quotewill return quoted code block and Elixir compiler will generate “normal” code (normal - I mean that code you can see - without AST) - it’s expanding instructions to real code.About your code:
both of them returns unquoted raw value of that expression.
What unquote is doing is like undo of one quote call and evaluate it putting into quoted expression.
When you are working for example with lists in recursive method like:
you need to implement also case when
do_somethingis called with empty list like:Similarly unquote works with raw values. You have quoted variable/expression
ntimes. unquote is doingundofor first (top)quote, but when it’s called with raw value then it just returns that value and finally in both cases it evaluates it.So:
Note: I used here raw value (5) that’s already unquoted.
OvermindDL1
Eh, not really like assembler, it is the very definition of AST. Elixir’s AST.
The compilation process goes: Elixir → Elixir’s AST (what
quotegives you) → Erlang (Abstract Format, basically it’s AST) → Core Erlang → BEAMWith a variety of translators along the way too.
Basically take this Elixir:
To this Elixir AST:
To this Erlang:
To this Core Erlang:
To this BEAM Assembly:
And that is what is loaded by the VM.
laiboonh
Nice code there to challenge one’s understanding of unquote but i think its more illustrative if we used something that is not an AST Literal