Prelude Macros

Macros loaded automatically before user code. These expand at compile time.

MacroDescription
defn srcLoaded automatically by the Expander before user code expansion. These are defmacro definitions — they register macros in the Expander's macro table and produce no runtime code. defn - function definition shorthand (defn f (x y) body...) => (def f (fn (x y) body...))
let* srclet - alias for let (retained for Scheme familiarity) let is already sequential; let expands to nested single-binding lets
-> src-> thread-first: insert value as first argument (-> val (f a) (g b)) => (g (f val a) b)
->> src->> thread-last: insert value as last argument (->> val (f a) (g b)) => (g b (f a val))
as-> srcas-> - thread with named binding (as-> val var (f var) (g var)) => binds val to var, threads through forms
some-> srcsome-> - thread-first, short-circuiting on nil (some-> val (f a) (g b)) => like -> but stops if any step returns nil
some->> srcsome->> - thread-last, short-circuiting on nil (some->> val (f a) (g b)) => like ->> but stops if any step returns nil
when srcwhen - execute body if test is truthy, return nil otherwise
unless srcunless - execute body if test is falsy, return nil otherwise
default srcdefault - supply a default value for a &named parameter (default x 42) assigns x to 42 only if x is nil (not provided). Unlike (or), this correctly preserves explicitly-passed false values.
yield srcyield - cooperative suspension (yield) => (emit :yield nil) (yield value) => (emit :yield value)
error srcerror - signal a fiber error (error) => (emit :error nil) (error value) => (emit :error value)
assert srcassert - check PRED; when falsy, signal a structured :failed-assertion that carries the predicate's unevaluated :syntax and its :value. For a recognized comparison (= a b) (or < > <= >= not=) it also records :actual (the LHS value) and :expected (the RHS value). Returns PRED's value when truthy. The error keyword stays :failed-assertion. See docs/test-runner.md and docs/compile-time.md. (Map literals don't splice under quasiquote, so the payload is built with struct.)
gate! srcCOND is evaluated at RUNTIME: the canonical predicate is (backend? :tier), and the same test closure is compiled once then dispatched to every tier by compile/run-on, so which tier is active — and thus whether the gate is open — is only known while running. (Map literals don't splice under quasiquote, so the :gated payload is built with struct, like assert's.)
try srctry/catch - error handling via fibers Usage: (try body... (catch e handler...)) The last form must be (catch binding handler-body...) Body forms run in a fiber that catches errors. If an error occurs, the catch handler runs with the error bound. If no error occurs, the body result is returned.
protect srcThe body may perform async I/O: an I/O request travels out to the scheduler through this fiber, and the completion's error comes back to it as [false err]. See docs/errors.md § "Cleanup around async I/O".
defer srcExample: (let [p (port/open "data.txt" :read)] (defer (port/close p) # cleanup: always runs, closes port (port/read-all p))) # body: reads contents, return value
with srcwith - resource management (acquire/release) Usage: (with binding ctor dtor body...) Acquires the resource, runs body, then releases via destructor. Errors in body are propagated after cleanup.
with-temp-dir srcwith-temp-dir - fresh scratch directory with guaranteed cleanup Usage: (with-temp-dir binding body...) Binds a uniquely-named directory under the platform temp root (file/mktempdir honors TMPDIR, so scratch space is redirectable without hardcoding /tmp), then deletes the whole tree after body — even when body errors.
yield* srcyield - delegate to sub-fiber Resumes the sub-fiber, yielding each of its values to the caller. Resume values from the caller are passed through to the sub-fiber. Returns the sub-fiber's final value when it completes.
ffi/defbind srcffi/defbind - convenient FFI function binding Usage: (ffi/defbind name lib-handle "c-name" return-type [arg-types...]) Expands to a wrapper function that looks up the symbol, creates a signature, and defines a function that calls it. Example: (ffi/defbind abs libc "abs" :int [:int]) => (def abs (let [ptr__ (ffi/lookup libc "abs") sig__ (ffi/signature :int [:int])] (fn (a0) (ffi/call ptr__ sig__ a0))))
each srcThe last arm walks an array by index, and three sources fill that array: a collection whose traits carry :iter, a set, and a struct's pairs. Anything else raises. The iterator is drained into the array rather than driven by a callback so that break and assign in BODY still reach the enclosing function; a closure per element would trap both. docs/traits.md holds the dispatch this arm completes.
case srccase - equality dispatch (flat pairs) (case expr val1 body1 val2 body2 ... [default]) Uses gensym to avoid double evaluation of the dispatch expression. Odd element count means the last element is the default.
if-let srcif-let - conditional binding (flat pairs) (if-let [x expr ...] then else) Each binding is evaluated and checked for truthiness. If any binding value is falsy, the else branch runs.
when-let srcwhen-let - conditional binding without else (flat pairs) (when-let [x expr ...] body...) Sugar for (if-let bindings (begin body...) nil)
when-ok srcwhen-ok - protect + destructure in one step (when-ok [val (expr)] body...) => runs body with val if expr succeeds Returns nil when expr errors (body is skipped).
forever srcforever - infinite loop (forever body...) Expands to (while true body...) Use (break) or (break value) to exit.
repeat srcrepeat - run body N times (repeat 3 (println "hi")) prints "hi" three times The count guard both reports a non-integer loudly and proves the loop counter comparison for the silent %lt (the count is a user expression the expansion site cannot otherwise type). (Map literals don't splice under quasiquote, so the error payload is built with struct, like assert's.)
apply srcapply - call function with args spread from final list argument (apply f args) => (f (splice args)) (apply f a b args) => (f a b (splice args))
ffi/with-stack srcffi/with-stack - scoped FFI stack allocations (ffi/with-stack [[p :int 42] [buf 64]] body...) Each binding is [name type value] for typed scalars or [name size] for raw buffers. Pointers are malloc'd, written, and freed on scope exit.
with-allocator srcwith-allocator - route heap allocations through a custom allocator (with-allocator alloc body...) => installs alloc, runs body in defer, uninstalls Values allocated within the body use the provided allocator. When the form exits, all custom-allocated objects are freed. Do not retain references to these objects beyond the form's dynamic extent.