Saltar al contenido

Higiene, Recursión y Argumentos de Bloque

En esta página

Higiene

Las variables creadas con let dentro del cuerpo de un macro reciben un sufijo único en la expansión. Esto significa que un let result dentro del macro nunca sobreescribe un result que ya existe en el ámbito del llamador. Puedes reutilizar nombres obvios como result, tmp e i sin temor a colisiones:

twice! e inc_tmp!/dec_tmp! demuestran que cada expansión aísla sus propios bindings.

05-hygiene.zolo
Playground
// Feature: Macro hygiene — internal vars do not leak to the caller

// Syntax: variables declared with `let` inside the body get a unique

// suffix on expansion, avoiding collisions with external names.

// When to use: you can reuse "obvious" names like `result`, `tmp`, `i`

// inside macros without fear of overwriting the caller's bindings.


// The macro declares `result` internally.

macro twice(x) {
  let result = $x * 2
  print("inside the macro: {result}")
}


// The caller also has `result` — it is not overwritten.

let result = 100
twice!(7)
print("outside: {result}")

// expected:

// inside the macro: 14

// outside: 100


// The same `tmp` name in three different macros — no collision.

macro inc_tmp(x) {
  let tmp = $x + 1
  print("inc: {tmp}")
}


macro dec_tmp(x) {
  let tmp = $x - 1
  print("dec: {tmp}")
}


let tmp = 999
inc_tmp!(10)
dec_tmp!(10)
print("original tmp: {tmp}")
// expected:

// inc: 11

// dec: 9

// original tmp: 999

Recursión

Un macro puede invocar a otro macro en su cuerpo. La expansión se resuelve recursivamente (límite de ~64 niveles). Esto permite componer reglas pequeñas en lugar de duplicar lógica — min3! reutiliza min2!, y min4! reutiliza ambos:

Cadena min2!min3!min4! y composición con double!(inc!(5)).

04-recursive.zolo
Playground
// Feature: Recursive macros — one macro calling another

// Syntax: the `outer` macro invokes `inner!(...)` in its body

// When to use: compose small macros to avoid duplicated code, modular

// textual rules (depth limit ~64).


// Basic block: minimum of two.

macro min2(a, b) {
  if $a < $b { $a } else { $b }
}


// Reuses min2 to build min3.

macro min3(a, b, c) {
  min2!($a, min2!($b, $c))
}


// And min4 reuses min3 + min2.

macro min4(a, b, c, d) {
  min2!(min2!($a, $b), min2!($c, $d))
}


print(min2!(7, 3))

// expected: 3


print(min3!(7, 2, 5))

// expected: 2


print(min4!(9, 4, 6, 1))

// expected: 1


// Composition also works with different expressions at each level.

macro double(x) {
  $x + $x
}


macro inc(x) {
  $x + 1
}


print(double!(inc!(5)))
// expected: 12   ((5 + 1) + (5 + 1))

Bloques como argumento

Cualquier parámetro puede recibir un bloque { ... }. En la expansión, el bloque se pega textualmente donde aparece $param, creando construcciones de control personalizadas. repeat_n! implementa un bucle; logged! envuelve el cuerpo con mensajes de inicio y fin:

repeat_n!(n, { ... }) y logged!(label, { ... }) como constructores de flujo de control.

06-block-arg.zolo
Playground
// Feature: Macros that receive a block as an argument

// Syntax: `name!(arg, { ...statements... })` — any arg can be a block

// inside `{}`, expanded textually wherever `$arg` appears.

// When to use: build custom "control-flow constructs" — retry, timed,

// with_lock, etc. — where the user passes the "body".


// Repeats a block N times, counting attempts.

macro repeat_n(times, body) {
  var __i = 0
  while __i < $times {
    __i = __i + 1
    $body
  }
}


repeat_n!(3, {
  print("tick")
})

// expected:

// tick

// tick

// tick


// Macro that wraps the body with try-style logging.

macro logged(label, body) {
  print("[start] {$label}")
  $body
  print("[done] {$label}")
}


logged!("important work", {
  let x = 10 + 20
  print("computed {x}")
})
// expected:

// [start] important work

// computed 30

// [done] important work

Desafío

Crea un macro timed!(label, body) que imprima "[start] label", ejecute body, y luego imprima "[end] label". Úsalo para envolver dos bloques distintos y verifica que los mensajes aparecen correctamente intercalados.

Consulta también

Buscar en Zolo

9 resultados

enespt-br