# macro/gensym
Generate a unique keyword value of the form `:prefix#N`. Each call
returns a distinct value; the counter is monotonic per process.
[macro/gensym "tmp"] # :tmp#0 [macro/gensym "tmp"] # :tmp#1 [macro/gensym "log"] # :log#2
## Syntax
[macro/gensym prefix]
`prefix` is a string; the result is `:<prefix>#<counter>`.
## When to use it
`macro/gensym` is for producing unique runtime values — opaque tokens,
unique map keys, sentinel values:
def session-id [macro/gensym "session"] # :session#5 — guaranteed unique [assoc $cache $session-id $payload]
## Runtime vs compile-time — the gotcha
Deft macros expand at compile time via syntactic substitution; the
macro body is inlined, not executed, during expansion. `[macro/gensym ...]`
runs at runtime, so a value it returns cannot become the literal
name of a new variable — deft `set` takes a literal identifier, not
a value:
defmacro with-temp {|body| set tok [macro/gensym "tok"] [macro/quote { set $tok "temp" # ✗ won't work — $tok is a value, not a name [macro/unquote $body] }] }
For compile-time symbol hygiene inside generated code, use
`macro/syntax-quote` instead — it auto-gensyms bare symbols *during
expansion*, producing fresh identifier names that the compiler then
treats as real variables:
defmacro swap {|a b| [macro/syntax-quote { set tmp $a # ← 'tmp' renamed to tmp#N at compile time set $a $b set $b $tmp }] }
## Notes
- The prefix is a string literal.
- The counter is process-global (shared across all runtimes in the
process); uniqueness is guaranteed within a single process, not
across them.
- The result is a keyword — comparable with `==`, usable as a map key.
## See Also
`macro/syntax-quote`, `macro/quote`, `macro/unquote`, `defmacro`