Macros
Each macro name in the table links to its own page, with a fuller description and a runnable example you can evaluate in your browser.
| Macro | Syntax | Description |
|---|---|---|
cond | (cond (test1 body1...) ...) | Conditional with multiple clauses. Returns body of first truthy test |
case | (case key (k1 body1...) ((k2 k3) body2...) (otherwise body...)) | Dispatch on a key compared with eql. Keys are unevaluated; a list key matches any element; t/otherwise is the default. Returns nil if nothing matches |
ecase | (ecase key (k1 body1...) ((k2 k3) body2...)) | Exhaustive case: no default clause (t/otherwise are ordinary keys), and an unmatched key signals an error |
ccase | (ccase key (k1 body1...) ...) | Like ecase; an unmatched key signals an error. rontolisp establishes no store-value restart around it, so it is identical to ecase (not correctable) |
and | (and expr1 expr2...) | Short-circuit AND. Returns first nil or last value. (and) returns t |
or | (or expr1 expr2...) | Short-circuit OR. Returns first non-nil value or nil. (or) returns nil |
when | (when condition body...) | Evaluates body when condition is true, returns nil otherwise |
unless | (unless condition body...) | Evaluates body when condition is nil, returns nil otherwise |
dotimes | (dotimes (var count result?) body...) | Evaluate body with var bound to 0..count-1. Returns result (or nil) |
do | (do ((var init step?)...) (end-test result...) body...) | Iterate with parallel-stepped variables. Returns the result forms when end-test is true |
do* | (do* ((var init step?)...) (end-test result...) body...) | Like do but bindings and steps are sequential (let*-style): each init/step form sees the variables already updated this iteration |
loop | (loop for i from 1 to n collect (f i)) | A bounded subset of the ANSI loop: numeric/list stepping (for), accumulation (collect/sum/count/...), and simple control clauses (while/repeat/when/finally/return). See the page for the full grammar and limitations |
prog1 | (prog1 first body...) | Evaluate all forms in order, return the value of first |
multiple-value-prog1 | (multiple-value-prog1 (floor 17 5) (cleanup)) | Like prog1 but returns ALL values of the first form |
prog2 | (prog2 first second body...) | Evaluate all forms in order, return the value of second |
time | (time form) | Evaluate form, print the elapsed real time to standard output (; Elapsed real time: N ms), and return the form's value. N is an integer of milliseconds on the interpreter/JVM and a float of milliseconds on WASM |
psetq | (psetq v1 e1 v2 e2 ...) | Parallel assignment: every right-hand side is evaluated before any variable is assigned. Returns nil |
psetf | (psetf place1 e1 place2 e2 ...) | psetq generalized to setf places: place subforms and values are all evaluated before any assignment. Returns nil |
block | (block name body...) | Named block: returns the last form's value or the value of a matching (return-from name v). The match is lexical on every backend, so a return-from inside a closure exits the block that encloses it in the source |
typecase | (typecase x (integer body...) (string body...) (t default...)) | Dispatch on the type of x. Supported type names: integer, float, number, rational, string, symbol, keyword, cons, list, null, atom, character, hash-table, boolean (plus t/otherwise), and the compound specifiers (or ...)/(and ...)/(not ...)/(member ...)/(eql ...)/(satisfies ...) and ranged numeric types like (integer 0 9). Returns nil if nothing matches |
etypecase | (etypecase x (integer body...) (string body...)) | Exhaustive typecase: no default clause, and an object whose type matches no clause signals an error |
ctypecase | (ctypecase x (integer body...) (string body...)) | Like etypecase; an object whose type matches no clause signals an error. rontolisp establishes no store-value restart around it, so it is identical to etypecase (not correctable) |
error | (error "bad value: ~a" x), (error 'my-error :v x), (error obj) | Signal an error, aborting execution unless a handler-case catches it. Designators: a literal control string (same directives as format), a quoted condition-type symbol with initargs (constructs a typed condition; the define-condition :report becomes the message), or a condition object. The interpreter and JVM throw an exception carrying the message and the condition; wasm-GC throws a WebAssembly exception when the program contains a catching form, and traps otherwise. Like format, it is a macro with no function value (#'error is unsupported) |
cerror | (cerror continue-format datum args...) | Signal a continuable error: a continue restart is established around the signal, so a handler-bind handler can call continue to resume past it with nil; otherwise behaves like error |
signal | (signal 'my-condition :v x) | Signal a non-fatal condition (same designators as error): raised to an established handler-case, otherwise returns nil and continues (always nil under --no-gc) |
handler-case | (handler-case expr (type (var) body...)... (:no-error (v) body...)) | Evaluate expr, dispatching a signaled error to the first clause whose condition type matches (rethrown when none does); :no-error runs on normal completion. Compile error under --no-gc |
ignore-errors | (ignore-errors form...) | The forms' value, or nil when an error is signaled; sugar over handler-case. Compile error under --no-gc |
handler-bind | (handler-bind ((type handler)...) body...) | Establish handlers that run at the signal point, before unwinding, so they can invoke a restart-case restart; a handler that returns declines. Compile error under --no-gc |
restart-case | (restart-case form (name (args...) body...)...) | Evaluate form with named restarts established; an invoked restart unwinds back here and runs its clause inline (a clause may go into an enclosing tagbody). Compile error-free everywhere; --no-gc keeps the primary-form-only lowering |
restart-bind | (restart-bind ((name fn)...) body...) | Establish restarts whose functions run at the invocation point (no unwinding) |
with-simple-restart | (with-simple-restart (name fmt args...) body...) | Sugar over restart-case: invoking the restart returns (values nil t) from the form |
setf | (setf place value) | Generalized assignment. Supports car, cdr, nth, first..fourth, rest, caXXXr as places |
push | (push item place) | Prepend item to list at place. Returns the new list |
pop | (pop place) | Remove and return the first element from list at place |
remf | (remf place indicator) | Remove key-value pair from property list at place. Returns t if found, nil otherwise |
let* | (let* ((x 1) (y x)) body...) | Sequential bindings: each init form sees the previous bindings. Expands to nested let |
dolist | (dolist (var list result?) body...) | Evaluate body with var bound to each element. Returns result (or nil) with var bound to nil |
incf | (incf place delta?) | Expands to (setf place (+ place delta)). delta defaults to 1. Returns the new value |
decf | (decf place delta?) | Expands to (setf place (- place delta)). delta defaults to 1. Returns the new value |
format | (format t "Hello ~a, ~d!~%" 'world 42), (format nil "~a" x) | Formatted output to standard output (t, returns nil) or to a string (nil) |
with-open-file | (with-open-file (s "f.txt" :direction :output) (write-line "hi" s)) | Open a file, bind the stream to s, evaluate the body, close the file. Returns the body value. Supports the :direction option (:input default, :output) and the :element-type option ('character default, '(unsigned-byte 8) for a binary stream); both must be literal |
with-open-stream | (with-open-stream (s (make-string-input-stream "hi")) (read-line s)) | Bind an ALREADY-OPEN stream, evaluate the body, close it. with-open-file without the open |
check-type | (check-type place typespec [string]) | Signal an error when the value of place is not of the given type; return nil when it is. Lite version: no restarts, so the place is never re-stored |
assert | (assert test-form [(place...) [datum args...]]) | Signal an error when test-form is false; return nil when it is true. The places list is accepted but ignored (no restarts) |
declare | (declare declaration...) | Parsed no-op: evaluates to nil, arguments never evaluated or validated |
declaim | (declaim declaration...) | Parsed no-op like declare, for file-level declarations |
proclaim | (proclaim declaration) | Parsed no-op like declaim (deviates from CL: classified as a macro, the argument is not evaluated) |
the | (the type form) | Returns the value of form unchanged; the type is not checked |
eval-when | (eval-when (situation...) body...) | Evaluates the body as a progn; every situation is treated as "evaluate now". Top-level bodies are spliced so nested defun/defmacro definitions are collected |
locally | (locally declaration... form...) | Evaluates the body as a progn; the leading declare forms are dropped (declarations are parsed no-ops) |
with-standard-io-syntax | (with-standard-io-syntax form...) | Binds *package* to cl-user and evaluates the body as a progn. Every other reader/printer control variable Common Lisp asks it to rebind is, in rontolisp, either informational (*read-default-float-format*) or unread by any reader/printer |
write-char | (write-char char [stream]) | Write one character (returning it); expands to write-string of the one-character string, so file and string streams work |
flet | (flet ((name lambda-list body...)...) body...) | Local, non-recursive function bindings (Lisp-2: call position and #'name). A definition body sees the outer function of the same name, not its siblings. Lambda lists support the defun extensions |
labels | (labels ((name lambda-list body...)...) body...) | Like flet but the definitions see each other (recursion and mutual recursion) |
symbol-macrolet | (symbol-macrolet ((name expansion)...) body...) | Local symbol macros: a free reference to name evaluates expansion in its place, and setq/setf of name assigns through the expansion place. Inner bindings of the same name shadow |
multiple-value-bind | (multiple-value-bind (var...) values-form body...) | Binds the variables to the values of the producer form. A literal (values ...) call, the multi-value built-ins (floor family, gethash, parse-integer) and a user function returning (values ...) supply all of their values. Extra variables bind to nil |
multiple-value-list | (multiple-value-list values-form) | Collects the producer's values into a list (recognized like multiple-value-bind) |
multiple-value-call | (multiple-value-call function values-form...) | Calls the function with all values of every producer as the arguments, including a user function's values spread at runtime (deviates from CL: classified as a macro, not a special operator) |
nth-value | (nth-value n values-form) | The n-th (0-based) value of the producer, or nil; expands to nth over multiple-value-list |
make-instance | (make-instance 'class-name :initarg value ...) | Create an instance of a defclass class (static CLOS subset). The class name may be literal or computed; the class SET is fixed at compile time |
slot-value | (slot-value object 'slot-name) | Read a slot of a defclass instance; a setf-able place. The slot name must be a literal quoted symbol |
with-slots | (with-slots (x (v y)) instance body...) | Bind slot names as symbol-macro-style places for the body: reads see the slots, and setf/push/incf of a bound name writes back to the slot. Resolves defstruct slots too |
with-accessors | (with-accessors ((x pt-x)) instance body...) | Bind variables as symbol-macro-style places standing for accessor calls on the instance |
change-class | (change-class obj 'class :initarg v) | Change an instance's class in place (identity kept, shared slots kept, new slots from their :initforms) and return it |
rontolisp:with-arena | (rontolisp:with-arena () body...) | Run the body and return its value, naming a memory-reclamation boundary for the non-GC WASM backend (--no-gc): everything allocated inside is popped at the end, keeping only the body's value. A plain progn on the other backends (a real GC already reclaims) |
rontolisp:with-mutex | (rontolisp:with-mutex (mutex-form) body...) | Acquire the mutex, run the body, and release it on every exit (a signalled error included). Real mutual exclusion on the interpreter and the JVM backend, where a served handler runs one virtual thread per request; a no-op on the single-threaded WASM backends |
torch:no-grad | (torch:no-grad body...) | Run the body with gradient recording disabled: the torch operations inside compute values but record nothing on the autograd tape (the training-loop update / inference idiom) |
uiop:if-let | (uiop:if-let ((a x) (b y)) then else) | Bind the variables in parallel like let, then take the then branch only when EVERY variable came out non-nil. A single un-nested binding ((uiop:if-let (x form) ...)) is accepted too |
uiop:when-let | (uiop:when-let ((a x)) body...) | uiop:if-let with an implicit progn body and no else branch: the body runs only when every variable came out non-nil, otherwise nil |
uiop:when-let* | (uiop:when-let* ((a x) (b (f a))) body...) | The sequential uiop:when-let: each form sees the bindings before it, and the first nil one short-circuits to nil without evaluating the rest |
uiop:with-deprecation | (uiop:with-deprecation (:style-warning) (defun old-f (x) x)) | Establish the wrapped definitions exactly as written. Lite: rontolisp has no deprecation-warning channel, so the level form is ignored and no warning is ever produced |
prog | (prog ((v init)...) tag-or-form...) | let + tagbody inside a block: go jumps between the body's tags and (return x) exits with x |
prog* | (prog* ((v init)...) tag-or-form...) | Like prog with sequential (let*-style) bindings |
shiftf | (shiftf a b 9) | Shift place values left, store the last value into the last place, return the first place's old value |
load-time-value | (load-time-value form) | Evaluates form once per occurrence in the source (lazily, on first use), not once per use |
define-compiler-macro | (define-compiler-macro name (params...) body...) | Rewrite calls to name at compile time; returning the &whole form declines. A hint: it is ignored when the body signals, when name is a standard operator, or under apply/funcall |
typep | (typep x '(unsigned-byte 8)) | Type test over the typecase specifier set; the specifier must be a literal (quoted) type |
slot-boundp | (slot-boundp obj 'slot) | Whether the slot holds a value: nil for an unknown slot, one written with no :initform and never supplied, or one slot-makunbound emptied |
slot-makunbound | (slot-makunbound obj 'slot) | Makes the slot unbound and returns the instance; a later read signals unbound-slot |
slot-exists-p | (slot-exists-p obj 'slot) | Whether the instance's class declares the slot, regardless of boundness; nil for a non-instance |
print-unreadable-object | (print-unreadable-object (obj stream :type t) body...) | Writes #<[type ]...> around the body's output; returns nil (:identity accepted, prints no address) |
with-package-iterator | (with-package-iterator (next pkgs :external) body...) | Lite: binds the iterator name to a local FUNCTION always reporting no more symbols (no intern table) |
with-hash-table-iterator | (with-hash-table-iterator (next table) body...) | Binds the iterator name to a local FUNCTION answering (values t key value) per call, (values nil nil nil) when exhausted; the table is snapshot on entry |
do-external-symbols | (do-external-symbols (s :rontolisp) (print s)) | Iterate a package's exported symbols (interpreter only: the compiled backends carry no package registry) |
do-symbols | (do-symbols (s :cl-user) (print s)) | Iterate every symbol ACCESSIBLE in a package -- its own plus what it inherits (interpreter only, same reason) |
with-compilation-unit | (with-compilation-unit (:override t) body...) | A progn around the body: the options only merge a deferred-warning report, and there is no compile-file to defer one from |
Macros have no function value: #'cond or (funcall 'setf ...) is an error. Convenience
accessors and predicates that expand inline in call position (first, rest, nth,
second..fourth, 1+, 1-, zerop, plusp, minusp, evenp, oddp) are listed
under Functions because they are also usable as function
values (#'first).