# macro/syntax-quote
Like `macro/quote`, but with two differences aimed at hygienic macro
code generation:
1. `$param` references are substituted (acts like the normal macro
body) — no need for `[macro/unquote ...]` around parameters.
2. Bare symbols (e.g. `tmp`) are automatically renamed to unique
gensym'd names (`tmp#N`), so they cannot collide with variables at
the call site.
## Syntax
[macro/syntax-quote expr]
## Why hygiene matters
Deft macros are not hygienic by default. A macro that introduces a
symbol like `tmp` can clobber a same-named variable in the caller's
scope:
defmacro swap {|a b| [macro/quote { set tmp $a # ← 'tmp' collides with caller's 'tmp'! set $a $b set $b $tmp }] } set tmp "outer" [swap x y] echo $tmp # ← clobbered by the macro's tmp
`macro/syntax-quote` fixes this by renaming `tmp` to a unique name
(`tmp#42`, `tmp#43`, …) every expansion:
defmacro swap {|a b| [macro/syntax-quote { set tmp $a # ← auto-gensym'd to tmp#N set $a $b set $b $tmp }] } set tmp "outer" [swap x y] echo $tmp # ← still "outer" — safe
## Substitution rules
| Inside `macro/syntax-quote` | Behaviour |
|----------------------|-----------|
| `tmp` (bare symbol) | Renamed to `tmp#N` |
| `$param` | Substituted with the macro argument |
| `:keyword` | Preserved literally |
| `set` / `if` / `for` / `while` / `begin` | Preserved (special forms, not gensym'd) |
| `__lambda` and other `__`-prefixed | Preserved (internal forms) |
| `[macro/unquote $expr]` | Substituted (rarely needed — `$param` already is) |
| `[macro/splice $list]` | Inlined into the parent form |
## Example: rest-collector + splice
defmacro build-code {|@exprs| [macro/syntax-quote { [begin [macro/splice $exprs]] }] } set a 1 set b 2 [build-code [set a 10] [set b 20]] # expands to: [begin [set a 10] [set b 20]]
## Escape with macro/unquote
`[macro/unquote $expr]` inside `macro/syntax-quote` is mostly redundant
(since `$param` is already substituted). It's occasionally useful for
forcing substitution of a non-`$param` expression:
defmacro with-logging {|body| [macro/syntax-quote { set log @{} [macro/unquote $body] }] }
Here `log` is gensym'd (hygiene), and the body block is inlined via
unquote.
## Important: use `[...]`, not `(...)`
Deft's bare `( ... )` parens are infix-only. `[macro/unquote $x]` is
correct; `(macro/unquote $x)` is a syntax error.
## See Also
`macro/quote`, `macro/unquote`, `macro/gensym`, `macro/splice`, `begin`,
`defmacro`