Prelude Macros
Macros loaded automatically before user code. These expand at compile time.
| Macro | Description |
|---|---|
defn src | Loaded 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* src | let - 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-> src | as-> - thread with named binding (as-> val var (f var) (g var)) => binds val to var, threads through forms |
some-> src | some-> - thread-first, short-circuiting on nil (some-> val (f a) (g b)) => like -> but stops if any step returns nil |
some->> src | some->> - thread-last, short-circuiting on nil (some->> val (f a) (g b)) => like ->> but stops if any step returns nil |
when src | when - execute body if test is truthy, return nil otherwise |
unless src | unless - execute body if test is falsy, return nil otherwise |
default src | default - 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 src | yield - cooperative suspension (yield) => (emit :yield nil) (yield value) => (emit :yield value) |
error src | error - signal a fiber error (error) => (emit :error nil) (error value) => (emit :error value) |
try src | try/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 src | WARNING: protect is synchronous. The body must not perform async I/O (port/open, port/read-line, tcp/connect, etc.). Use protect inside ev/spawn if you need error capture around async work. |
defer src | Example: (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 src | with - 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. |
yield* src | yield - 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 src | ffi/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 src | each - iterate over a sequence Dispatches on type-of: lists use first/rest, indexed types use get/length. (each x coll body...) or (each x in coll body...) |
case src | case - 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 src | if-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 src | when-let - conditional binding without else (flat pairs) (when-let [x expr ...] body...) Sugar for (if-let bindings (begin body...) nil) |
when-ok src | when-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 src | forever - infinite loop (forever body...) Expands to (while true body...) Use (break) or (break value) to exit. |
repeat src | repeat - run body N times (repeat 3 (println "hi")) prints "hi" three times |
apply src | apply - 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 src | ffi/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 src | with-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. |