All pages
Truth, iteration and values
Truth and staging
nil and false are false; every other ordinary value is true, including
zero, the empty string and an empty vector. if, when, unless, cond,
and, or, not, truthy, filter and assert all use this rule.
and and or return the deciding value itself, not a boolean.
A tensor, a parameter or a ctx scalar used as a condition is
E-FLOW-001. Shapes are static and both branches must exist in the graph,
so select elementwise instead:
(if (> x 0.0) x 0.0) ; E-FLOW-001: x is a tensor
(where (> x 0.0) x (zeros-like x)) ; the graph computes both, picks per element
(if (> (dim x 0) (dim x 1)) ...) ; fine: dim is an ordinary integer
Shape queries (shape, rank, dim, numel, dtype) return ordinary
values, so compile-time decisions on shapes are plain ifs. That is how
Muon transposes a tall matrix; see sexpgpu/optim.
Iteration
| form | behavior |
|---|---|
(dotimes (i count [result]) body...) | evaluates count once, runs the body for i from 0 below it; a negative count runs nothing; result sees i equal to the iteration count |
(dolist (item list [result]) body...) | evaluates the list once, runs the body per element; result sees item bound to nil |
(repeat n f) | calls f with 0..n-1 and collects the results: how a stack of blocks is built |
(map f xs), (filter f xs), (reduce f init xs) | collecting and folding; see builtins |
dotimes and dolist collect nothing: they return result, or nil
without one, and preserve its multiple values. Their loop variable is one
binding shared across iterations. With a tensor accumulator they unroll
into the graph:
(let ((result (zeros-like x)))
(dotimes (i degree result)
(setq result (+ result (* (sum (slice coefficients 0 i (+ i 1))) (pow x i))))))
Multiple values
(values expr...) returns zero or more values. Ordinary arguments,
variable initializers, assignments, vector elements and training contract
components take the primary value; zero values give nil there. The last
form of a body and the chosen branch of if keep all values.
| form | behavior |
|---|---|
(values-list list) | the list's elements as values |
(multiple-value-list expr) | all returned values as a list |
(multiple-value-bind (names...) expr body...) | binds the values; missing ones are nil, extras discarded |
(multiple-value-call f expr...) | calls f with every value of every expr, concatenated |
(multiple-value-prog1 expr body...) | returns expr's values after running the body |
sexpgpu eval prints several values as #<values ...>.
Errors on purpose
(error message...)stops compilation withE-EVAL-001and the message.(assert test [message])stops withE-EVAL-002whentestis false:(assert (= 2 (rank param)) "muon updates matrices").
Both point at the line that raised them, or at your model application when raised inside a library. See check.
Related: It is Common Lisp, tensor operations.