Meta-programming in Elixir allows writing code that generates and manipulates other code. This is useful for creating Domain-Specific Languages (DSLs), reducing boilerplate, and implementing compile-time optimizations.
This is how Elixir code is represented, as an AST.
So when a function or expression is parsed, it’s broken down into tokens (Lexing) and then structured into the AST.
ast = quote do: 1 + 2
IO.inspect(ast) # {:+, [context: Elixir, import: Kernel], [1, 2]}
quote do: 1 + 2 → Returns the AST representation of 1 + 2 instead of evaluating it.Macro.to_string/1 → Converts an AST back into human-readable code.quote and unquoteThe quote function captures expressions as AST instead of evaluating them.
Whereas the unquote function forces the evaluation of an expression inside a quote.
x = quote do: 1 + 2
quote do: 3 * unquote(x)
# This results in AST for `3 * (1 + 2)`
// If no unquote, x would be treated as a literal AST instead of evaluated.
A Macro function takes an AST as input and returns another AST.
defmacro inspect_macro(x) do
IO.inspect(x) # Print AST of x
end
//The inspect function Inspects and writes the given item to the standard output.