Skip to content

Definition and Invocation

A macro is declared with the macro keyword, followed by the name, the parameters in parentheses, and the body in braces. Inside the body, each parameter is referenced with the $ prefix. The invocation uses name!(arg) — the trailing ! is the visual convention that distinguishes macros from function calls.

The argument can be any expression: a literal, arithmetic, a function call. The substitution is textual, so double!(5 + 5) expands to (5 + 5) + (5 + 5):

Single-parameter macro: double! demonstrates textual substitution with literals, arithmetic, and a function call.

01-basics.zolo
Playground
// Feature: Macros — basic definition
// Syntax: `macro name(p1, p2) { ... }` + invocation `name!(arg)`
// When to use: generate repetitive code at expansion time (before
// typecheck and lowering). Useful to wrap textual patterns that a
// function cannot capture — `stringify!`, `assert!`, `dbg!`, etc.

// Simplest macro: doubles the received expression.
// Note: parameters are referenced with `$name` in the body.
macro double(x) {
  $x + $x
}


// Invocation uses `!` at the end — convention that distinguishes from a regular function.
let result = double!(21)
print(result)

// expected: 42

// The argument can be any expression — it is pasted textually.
print(double!(5 + 5))

// expected: 20

// Macros are purely syntactic: you can pass identifiers, function
// calls, literals, arithmetic expressions...
fn ten() -> int {
  return 10
}

print(double!(ten()))
// expected: 20

When more than one value needs to be combined, declare multiple parameters. show_pair! illustrates string interpolation with two parameters; pick! uses three to implement an inline conditional:

sum3!, show_pair!, and pick! show multiple parameters and conditional expansion.

02-multiple-params.zolo
Playground
// Feature: Macros with multiple parameters
// Syntax: `macro name(a, b, c) { ... }` — any fixed number of params
// When to use: combine or compare multiple expressions at one expansion
// site.

// Sum of three expressions.
macro sum3(a, b, c) {
  $a + $b + $c
}


print(sum3!(1, 2, 3))

// expected: 6

// Print two arguments with a label.
macro show_pair(label, value) {
  print("{$label} = {$value}")
}


show_pair!("count", 42)
show_pair!("name", "zolo")

// expected:
// count = 42
// name = zolo

// Ternary comparison via macro.
macro pick(cond, a, b) {
  if $cond { $a } else { $b }
}


let x = 7
let max = pick!(x > 5, x, 5)
print(max)
// expected: 7

Challenge

Create a macro clamp!(val, lo, hi) that returns lo if val < lo, hi if val > hi, or val otherwise. Test with clamp!(15, 0, 10) and clamp!(-5, 0, 10).

See also

enespt-br