(rontolisp) docs

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.

MacroSyntaxDescription
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).