Skip to content

Function Reference

Every ELPS builtin, macro and library function in elps v1.95.0, from its docstring.

This page lists every function, macro, special operator and variable of ELPS v1.95.0, the release the examples on this site run. It is generated from the docstrings in luthersystems/elps, the same text elps doc <name> prints. For examples and guidance, see the Standard Library and the Language Guide.

Functions of the lisp package need no prefix. Call a function of another package with its package name, such as string:join.

Package Description
base64 Base64 encoding and decoding using the standard alphabet (RFC 4648).
elpspath Path-based access and mutation for nested data structures.
golang Go interop: extract strings, integers, and floats from native Go objects, and read struct fields via reflection.
help Interactive documentation: inspect functions, variables, and package exports.
json JSON serialization and deserialization. Marshal ELPS values to JSON bytes or strings and unmarshal JSON into ELPS data structures. Output is plain JSON, readable by standard JSON tools such as jq and when retrieved from a database or file system. In plain and canonical output, the sentinel json:null and () serialize as JSON null at any value position, including nested maps, lists, and arrays. Typed output writes () as null and json:null as the symbol "~$json:null". All load functions decode JSON null as (), never as the json:null symbol. Decoded maps accept string and symbol keys by name but always print and dump string keys. Keyword names retain their leading colon; use string keys for JSON interchange.
lisp The core ELPS language package. Provides fundamental data types, control flow, function and macro definition, package management, error handling, collections, I/O, and the type system.
math Mathematical functions: trigonometry, logarithms, exponents, absolute value, floor/ceiling, and mathematical constants (pi, inf).
regexp Regular expression compilation and matching using Go RE2 syntax.
s Schema validation: define typed validators with constraints and check values against them at runtime. Validators compose to describe complex data structures.
string String manipulation: case conversion, splitting, joining, repetition, trimming, and prefix, suffix and substring tests.
testing Test framework: define named tests and benchmarks with assertion helpers (assert-equal, assert-nil, assert-not-nil, etc.).
time Time operations: parsing, formatting, comparison, and arithmetic on UTC timestamps and durations. Wraps Go's time package.

base64

Base64 encoding and decoding using the standard alphabet (RFC 4648).

base64:decode

function: (base64:decode base64-data)

Decodes base64-encoded data and returns the result as bytes. The argument may be a string or bytes value containing valid standard base64. Returns an error if the input is not valid base64. The decoded byte length must fit the allocation limit; padding and ignored CR/LF characters do not count toward it.

base64:encode

function: (base64:encode data)

Encodes data using standard base64 encoding and returns the result as bytes. The argument may be a string or bytes value. The encoded byte length, including padding, must fit the allocation limit.

elpspath

Path-based access and mutation for nested data structures.

Paths are given as positional ELPS values — one argument per path step, no string DSL. Path step types:

  string    map key         "foo"
  int       array index     0, -1
  symbol    iterate all     '*
  list      array slice     '(range 1 3), '(range 1)

? reads without copying. ?set, ?del and ?nil copy the document's maps, lists and vectors; their "!" forms mutate in place. In-place edits of list elements are refused; use a copying form or a vector instead. An out-of-range integer index leaves the document unchanged on a write (and returns nil on a read). Negative indexes count from the end.

Tagged values and quote wrappers are rebuilt recursively by copying writes and traversed by cycle checks, but cannot be indexed into. Other value types are opaque leaves, including symbols, bytes, functions and natives. Reads may return them and writes may store them. A further path step into a leaf raises an error naming its type and location. Copies share opaque leaves by reference; mutation of their storage outside elpspath is visible through both documents. Containers must be acyclic, and arrays must have exactly one dimension; every operation checks this throughout the document, including off-path containers and the contents of tagged values and quote wrappers. New values pass the same container check. Function bodies and captured environments remain opaque and shared; they are not walked.

An iterator retains its per-element error handling: reads substitute nil for a failed element path, and writes leave that element unchanged.

Iterators count their work: one unit per element visited and per path step taken below it, plus the containers copied or shifted under them. Past 2^20 units in one call, each further unit is charged as one evaluation step, and the call checks the evaluation's deadline as it goes. Running out of steps or time stops the whole call with the evaluator's own condition (step-limit-exceeded, step-budget-exceeded or context-cancelled); a mutating form keeps the changes it already made. Calls below the allowance cost the steps they always did.

For ?set! and ?set, the last argument is the new value; all preceding arguments are path steps.

parse-path is the one function that takes a string: it converts a jq-style path into a list of the steps above, for a path that arrives as a string and is used more than once.

  (apply ? (cons obj (parse-path ".items[0].id")))

elpspath:?

function: (elpspath:? val &rest steps)

Get value at a path specified by positional args.

Each arg is a path step: string for map key, int for array index, '* to iterate all elements, '(range from to) for array slice. The slice end is optional: '(range from) runs to the end.

Values of any leaf type may be read. Descending into a leaf raises an error naming its type and path. A missing key or out-of-range integer index returns nil. Results may share storage with obj.

(? obj "foo" 0 "bar") => value at foo[0].bar (? users '* "name") => list of all user names (? scores '(range 1 3)) => elements [1,3) (? scores '(range 1)) => elements [1,end) (? scores '(range -2)) => the last two elements (? obj) => obj itself (no path steps)

Accepts at most 1024 nested iterator steps; deeper traversal raises a depth error.

elpspath:?del

function: (elpspath:?del val &rest steps)

Delete value at a path specified by positional args, returning a copy.

Out-of-range integer indexes return an unchanged copy. Containers are copied recursively through tagged/quote wrappers; opaque leaves, including functions, are shared by reference. Quoted lists stay quoted on an out-of-range integer no-op but become unquoted after an in-range integer edit.

(?del obj "foo") => new obj with foo removed (?del obj "items" 1) => new obj with items[1] removed

Iterative copying beyond 1000000 levels raises an ordinary depth error.

Accepts at most 1024 nested iterator steps; deeper traversal raises a depth error. Copying path chains longer than 1024 steps also raise a depth error.

elpspath:?del!

function: (elpspath:?del! val &rest steps)

Delete value at a path specified by positional args, mutating the original.

Out-of-range integer indexes are no-ops. List element mutation is refused.

(?del! obj "foo") => obj with foo removed (mutated) (?del! obj "items" 1) => obj with items[1] removed (mutated) (?del! records '* "cache") => remove cache key from all elements

Accepts at most 1024 nested iterator steps; deeper traversal raises a depth error.

elpspath:?nil

function: (elpspath:?nil val &rest steps)

Set value at a path to nil, returning a copy. The key is kept.

Out-of-range integer indexes return an unchanged copy. Containers are copied recursively through tagged/quote wrappers; opaque leaves, including functions, are shared by reference. Quoted lists stay quoted on an out-of-range integer no-op but become unquoted after an in-range integer edit.

(?nil obj "foo") => new obj with foo=nil (?nil patient "ssn") => new obj with ssn=nil

Iterative copying beyond 1000000 levels raises an ordinary depth error.

Accepts at most 1024 nested iterator steps; deeper traversal raises a depth error. Copying path chains longer than 1024 steps also raise a depth error.

elpspath:?nil!

function: (elpspath:?nil! val &rest steps)

Set value at a path to nil, mutating the original. The key is kept.

Out-of-range integer indexes are no-ops. List element mutation is refused.

(?nil! obj "foo") => obj with foo=nil (mutated) (?nil! rows '* "cached") => nil out cached on all elements

Accepts at most 1024 nested iterator steps; deeper traversal raises a depth error.

elpspath:?set

function: (elpspath:?set val &rest steps-and-value)

Set value at a path specified by positional args, returning a copy.

The last argument is the new value; all preceding arguments are path steps. The original is not modified. Any leaf type may be stored. Out-of-range integer indexes return an unchanged copy. Quoted lists stay quoted on an out-of-range integer no-op but become unquoted after an in-range integer edit.

Maps, lists, vectors and tagged/quote wrappers in the SOURCE document are copied recursively; opaque leaves (including bytes, functions and native values) are shared. The new value is stored BY REFERENCE, not copied: the value you supply becomes reachable and mutable through the result, so a later in-place write through the result (?set!, ?del!, append!) reaches the caller's value, and vice versa. Pass a copy if the result must not alias it.

(?set obj "foo" "bar" "new") => new obj with foo.bar="new" (?set obj "items" 0 "x") => new obj with items[0]="x"

Iterative copying beyond 1000000 levels raises an ordinary depth error.

Accepts at most 1024 nested iterator steps; deeper traversal raises a depth error. Copying path chains longer than 1024 steps also raise a depth error.

elpspath:?set!

function: (elpspath:?set! val &rest steps-and-value)

Set value at a path specified by positional args, mutating the original.

The last argument is the new value; all preceding arguments are path steps. Returns the mutated original. Any leaf type may be stored. Out-of-range integer indexes are no-ops. List element mutation is refused; use ?set or a vector instead.

The new value is stored BY REFERENCE, not copied: after the call it is reachable and mutable through the result, and a later write through either name is visible through the other.

(?set! obj "foo" "bar" "new") => obj with foo.bar="new" (mutated) (?set! obj "items" 0 "x") => obj with items[0]="x" (mutated) (?set! data '* "active" true) => set active=true on all elements

Accepts at most 1024 nested iterator steps; deeper traversal raises a depth error.

elpspath:parse-path

function: (elpspath:parse-path selector)

Convert a jq-style path string into a list of positional path steps.

The steps are what the ? family takes, so the result applies straight into any of them:

(parse-path ".items[0].id") => '("items" 0 "id") (parse-path ".items[].id") => '("items" * "id") (parse-path ".items[1:3]") => '("items" '(range 1 3)) (parse-path ".items[1:]") => '("items" '(range 1)) (parse-path ".") => '()

(apply ? (cons obj (parse-path sel))) (apply ?set (concat 'list (list obj) (parse-path sel) (list v)))

This is for a path that ARRIVES AS A STRING and is used more than once -- convert it once, keep the steps, and every later operation skips the parse.

KEY SYNTAX. A bare .key is the classic identifier rule, [A-Za-z_][A-Za-z_0-9]*, which is jq's rule too. Underscores and digits are fine, so the snake_case keys these paths usually address need nothing special:

(parse-path ".field_mask.paths") => '("field_mask" "paths")

Anything else -- a hyphen, a leading digit, "$", non-ASCII -- MUST be bracketed and quoted, as it must in jq:

(parse-path ".my-key")        => error: failed to parse: -key
                                 (the error explains this rule)
(parse-path ".[\"my-key\"]")   => '("my-key")
(parse-path ".[\"\"]")         => '("")

The jq optional-selector suffix "?" is accepted and DISCARDED -- ".a?" is exactly ".a" -- because nothing in the engine suppresses errors per step.

A malformed selector RAISES. It does not return an empty list: no steps is the identity path, so a swallowed error would make a bad selector address the whole document.

A selector may not SPAN LINES, and that raises for the same reason:

(parse-path ".[0] .password") => error: selector may not span lines

The jq-string grammar this shares cuts a bracket-led selector at its first newline and DISCARDS the rest, which would convert the selector above to the single step 0 -- a live path to the whole element. (apply ?set ...) through it would overwrite the record instead of its "password" field, silently.

Converting on each call is slower than one string-path operation, since it parses AND builds a list. How much the caching is worth depends on document size -- every operation first walks the whole document to validate it, so on a large document the parse is noise and on a small one it dominates.

golang

Go interop: extract strings, integers, and floats from native Go objects, and read struct fields via reflection.

golang:float

function: (golang:float native-value)

Extracts a Go float from a native value and returns it as an ELPS float. Accepts native values with underlying kind float32 or float64.

golang:int

function: (golang:int native-value)

Extracts a Go integer from a native value and returns it as an ELPS int. Accepts any native value with an underlying integer kind (signed or unsigned). Returns an error on overflow.

golang:string

function: (golang:string native-value)

Extracts a Go string from a native value and returns it as an ELPS string. The native value must hold a Go string or a type with underlying kind string. Does not convert non-string types to strings (use to-string for that). Non-native arguments, including ELPS strings, return an error.

golang:struct-field

function: (golang:struct-field native-struct field-name)

Reads an exported field from a native Go struct value using reflection. field-name is a string or symbol naming the field (must start with an uppercase letter). Returns the field value as a native value. Automatically dereferences pointers. Promoted fields are supported; a field reached through a nil embedded pointer returns an error: field NAME is reached through a nil embedded pointer.

help

Interactive documentation: inspect functions, variables, and package exports.

help:help-package

function: (help:help-package pkg-name)

Prints documentation for exported symbols in the specified package. pkg-name is a symbol, e.g. (help-package 'math).

help:help-package-symbols

function: (help:help-package-symbols pkg-name &optional all)

Prints symbols defined in the specified package. If a second argument is given which evaluates as true then unexported symbols in the package will also be printed.

help:help-packages

function: (help:help-packages)

Lists all packages loaded in the runtime with their descriptions.

json

JSON serialization and deserialization. Marshal ELPS values to JSON bytes or strings and unmarshal JSON into ELPS data structures. Output is plain JSON, readable by standard JSON tools such as jq and when retrieved from a database or file system. In plain and canonical output, the sentinel json:null and () serialize as JSON null at any value position, including nested maps, lists, and arrays. Typed output writes () as null and json:null as the symbol "~$json:null". All load functions decode JSON null as (), never as the json:null symbol. Decoded maps accept string and symbol keys by name but always print and dump string keys. Keyword names retain their leading colon; use string keys for JSON interchange.

json:canonize

function: (json:canonize object)

Returns a fresh plain JSON image as elps canonical JSON. Symbols and keywords become strings (true/false remain booleans, json:null becomes ()); lists become vectors, bytes become base64 strings, tags and quotes unwrap, and map keys become strings. Whole-number floats within +/-2^53 and platform int range become ints, including 0.0; other finite floats keep their type.

For every successful result c = (json:canonize v), exact value AND
numeric type equality holds (plain numeric JSON; pass
:string-numbers false when package defaults differ):
  (json:load-string (json:dump-string c) :exact-integers true) == c
  c == (json:load-string (json:dump-string c :typed true) :typed true)
  (json:dump-string c) == (json:dump-string c :typed true)
  (json:canonize c) == c
  c == (json:load-string (json:dump-string v) :exact-integers true)
If canonize succeeds, adopting it does not change dump bytes:
  (json:dump-bytes c) == (json:dump-bytes v)
Default load uses floats; use :exact-integers true for this invariant.

Raises json:canonize-error with the value and path for leading ~ strings/keys, invalid UTF-8 (including surrogate encodings), ints beyond +/-2^53, NaN/Inf, negative zero, whole-number floats beyond 2^53 or platform int range, int keys, converted key collisions/order changes, unsupported values and opaque native encodings/numbers. Other mixed keys are accepted. Keys sort by UTF-8 bytes. Ignores package number defaults. Cycles, depth beyond 1024 and allocation/step limits also raise. Every data rejection uses this ordinary catchable condition, never internal-panic. A handler receives (condition message case path), where case is a keyword: :leading-tilde, :invalid-utf8, :int-range, :float-range, :negative-zero, :non-finite, :key-type, :key-collision, :key-order, :depth, :cycle, :unsupported or :limit (bytes/value count). The message includes the case, offending value and path; path is also a separate string. handler-bind and ignore-errors can catch it, including from dump's :canonize option. Runtime step-budget and cancellation conditions propagate unchanged, as in other builtins.

Example:
  (json:dump-string (json:canonize '(a :b 1.0 ())))
  ; => "[\"a\",\":b\",1,null]"
  (equal? (json:dump-bytes (json:canonize '(a 1.0))) (json:dump-bytes '(a 1.0)))
  ; => true
  (let ([payload "~draft"]) (handler-bind ([json:canonize-error (lambda (_condition _message case _path) (if (equal? case :leading-tilde) (json:dump-string payload) (rethrow)))]) (json:dump-string (json:canonize payload))))
  ; => "\"~draft\""

See docs/typed-json.md for adoption and exact equality rules.

json:dump-bytes

function: (json:dump-bytes object &key string-numbers canonize typed)

Serializes an ELPS value to JSON bytes. Sorted-maps become objects, arrays become JSON arrays, and json:null and () become null, including inside containers (typed output keeps json:null as a symbol). Output is plain JSON, readable by standard JSON tools and when retrieved from a database or file system. :string-numbers controls whether numbers become strings (default: serializer setting). :canonize true is a short form of (json:dump-bytes (json:canonize v) :string-numbers false) and propagates exactly canonize's errors. :typed true is a short form of (json:dump-bytes (json:tag v) :string-numbers false). It preserves types with Transit-verbose tags: keywords "~:k", symbols "~$s", bytes "~b...", lists ["~#list",[...]], large ints "~n..." and special floats "~z...". Vectors remain arrays and nil remains null. Only leading ~ strings/keys gain an extra ~; caret and backquote are ordinary text. Whole floats use "~d" plus plain shortest round-trip text, including "~d1", "~d-0" and "~d1e+21". Other floats remain JSON numbers. Both modes ignore package number defaults. Canonical dumping honors explicit :string-numbers; typed dumping rejects that keyword, even false. Combining :typed and :canonize writes identical canonical bytes. Typed mode rejects functions, native values, errors, nested quotes, invalid UTF-8 and cycles; typed/canonical modes enforce depth 1024, value-count, allocation and step limits. Plain dumping retains its configured value-depth and allocation limits, and charges one step per KiB of output as it writes. It refuses a native value whose output would pass the allocation limit, or that nests more than 50000 levels, before marshalling it.

If you hash an elps value or use it as a cache/state key, hash (json:dump-string v :canonize true). Those bytes are frozen. For string-keyed data they equal plain dump, so existing hashes stay valid. Let a canonize error fail the operation. Don't hash :typed output of non-canonical values, printed forms, or anything that depends on json:use-string-numbers. Pass :string-numbers false explicitly for stable numeric JSON. See docs/typed-json.md, Hashing guidance.

Example:
  (to-string (json:dump-bytes (sorted-map 'id 7 'tags '(:a)) :typed true))
  ; => "{\"~$id\":7,\"~$tags\":[\"~#list\",[\"~:a\"]]}"
  (equal? (json:dump-bytes '(a 1.0) :canonize true) (json:dump-bytes (json:canonize '(a 1.0))))
  ; => true

See docs/typed-json.md for every tag and combination.

json:dump-message

function: (json:dump-message object &key string-numbers canonize typed)

Serializes an ELPS value to a native JSON message suitable for embedding in Go structures or passing back to a dump function. In plain and canonical output, json:null and () serialize as JSON null, including inside containers; typed output keeps json:null as a symbol. :string-numbers controls whether numbers are JSON strings (default: serializer setting). :canonize true first calls canonize and propagates its errors; :typed true preserves types with Transit-verbose tags. Both modes ignore package number defaults. Canonical dumping honors explicit :string-numbers; typed dumping rejects that keyword. Combining :typed and :canonize writes the same canonical bytes. Plain dumping raises beyond the configured value-depth or allocation cap; typed/canonical modes also enforce their shared limits.

Example:
  (to-string (json:message-bytes (json:dump-message '(a 1.0) :canonize true)))
  ; => "[\"a\",1]"
  (json:load-message (json:dump-message :pending :typed true) :typed true)
  ; => :pending

json:dump-string

function: (json:dump-string object &key string-numbers canonize typed)

Serializes an ELPS value to a JSON string. Like dump-bytes but returns a string. Output is plain JSON, readable by standard JSON tools and when retrieved from a database or file system. json:null and () become JSON null at any value position, except that typed output keeps json:null as a symbol. Plain map keys keep their full names: :height becomes ":height". :string-numbers controls whether numbers become strings (default: serializer setting). :canonize true first calls canonize and propagates exactly its errors; :typed true preserves types with Transit-verbose tags. Both modes ignore package number defaults. Canonical dumping honors explicit :string-numbers; typed dumping rejects that keyword, even false. Combining :typed and :canonize writes the same canonical bytes. Keys sort by UTF-8 bytes before JSON escaping; <, >, &, U+2028 and U+2029 always use lowercase Unicode escapes. This is elps canonical JSON; outside RFC 8785/JCS verifiers can differ. Limits and type restrictions match dump-bytes.

If you hash an elps value or use it as a cache/state key, hash (json:dump-string v :canonize true). Those bytes are frozen. For string-keyed data they equal plain dump, so existing hashes stay valid. Let a canonize error fail the operation. Don't hash :typed output of non-canonical values, printed forms, or anything that depends on json:use-string-numbers. Pass :string-numbers false explicitly for stable numeric JSON. See docs/typed-json.md, Hashing guidance.

Example:
  (json:dump-string '(a :b 1.0 ()) :canonize true)
  ; => "[\"a\",\":b\",1,null]"
  (json:dump-string (vector "^draft" "~draft") :typed true)
  ; => "[\"^draft\",\"~~draft\"]"
  (equal? (json:dump-string "<>&" :typed true) (json:dump-string "<>&"))
  ; => true

json:load-bytes

function: (json:load-bytes json-bytes &key string-numbers exact-integers typed strict)

Parses JSON bytes into ELPS values. Plain objects become sorted-maps with string keys, arrays become vectors, null becomes (), and numbers become floats by default. :string-numbers returns numbers as strings; :exact-integers returns integer literals as ints (default: serializer settings). :typed true is a short form of (json:untag (json:load-bytes b :strict true :exact-integers true :string-numbers false)). It restores every dumped type: vectors are plain arrays, nonempty lists use ~#list, and nil is null. Ignores package defaults and :exact-integers; rejects any explicit :string-numbers. :strict true checks canonical plain spelling. Typed input must have no whitespace, sorted keys, canonical number text and exactly the encoder's escapes (including Unicode escapes for <, >, &, U+2028 and U+2029). Unknown tags and alternate spellings raise. The result is fresh; costs one step per KiB.

Example:
  (json:load-bytes (json:dump-bytes '(1 :a) :typed true) :typed true)
  ; => '(1 :a)

json:load-message

function: (json:load-message json-message &key string-numbers exact-integers typed strict)

Parses a native JSON message produced by dump-message or a json.RawMessage supplied by an embedder. Plain decoding retains string map keys; :string-numbers returns numbers as strings, and :exact-integers returns integer literals as ints (default: serializer settings). :typed true uses the strict typed decoder, ignores package defaults and :exact-integers, and rejects explicit :string-numbers. :strict true rejects whitespace, duplicate keys, key order changes, and escapes or number text that plain dump does not produce.

Example:
  (json:load-message (json:dump-message '(1 :a) :typed true) :typed true :exact-integers true)
  ; => '(1 :a)

json:load-string

function: (json:load-string json-string &key string-numbers exact-integers typed strict)

Parses a JSON string into ELPS values, like load-bytes. Plain maps retain string keys and numbers become floats by default. :string-numbers returns numbers as strings; :exact-integers returns integer literals as ints (default: serializer settings). :typed true uses the strict typed decoder, ignores package defaults and :exact-integers, and rejects explicit :string-numbers. Typed integers are always exact and must fit the platform int. Large integer values require ~n; ~i is only for keys. Leading caret and backquote are ordinary text. Alternate string escapes, unsorted keys, whitespace, unknown tags and tagged empty lists raise. The result shares nothing.

Example:
  (json:load-string "{\"~$id\":7,\"~$tags\":[\"~#list\",[\"~:a\"]]}" :typed true)
  ; => (sorted-map 'id 7 'tags '(:a))
  (json:load-string "\"^draft\"" :typed true)
  ; => "^draft"
  (json:load-string (json:dump-string "<>&") :typed true)
  ; => "<>&"

json:message-bytes

function: (json:message-bytes json-message)

Extracts the raw byte content from a native JSON message object (one produced by dump-message, or a json.RawMessage supplied by an embedder). Returns a bytes value. Use this to get the underlying bytes of a message for further processing.

json:null

variable

The output-only JSON null sentinel symbol. Serializes as JSON null at any value position, including nested maps, lists, and arrays, just like (). Loading JSON null returns (), never this symbol.

json:string-numbers?

function: (json:string-numbers?)

Returns true if the JSON serializer's default string-numbers mode is on and false otherwise. It is false unless use-string-numbers enabled it. Dump and load functions use it for plain calls without :string-numbers; canonical dumping and typed dump/load ignore it. The mode belongs to the environment: a mode set while a program loads is inherited by every VM forked from its template, and a mode set inside one VM affects only that VM.

json:tag

function: (json:tag object)

Returns a plain JSON value that preserves the input's data types. Keywords use "~:k", symbols "~$s", bytes "~b...", and lists use ["~#list",[...]]. Whole floats use "~d" plus plain float text: "~d1", "~d-0", or "~d1e+21". Non-whole floats remain numbers. Leading ~ strings gain one ~. Unsupported values raise an error. (json:dump-bytes (json:tag v) :string-numbers false) returns the bytes of (json:dump-bytes v :typed true).

json:untag

function: (json:untag object)

Restores the data types represented by tag. Input must contain plain JSON values. Unknown tags and malformed forms raise an error. (json:untag (json:load-bytes b :strict true :exact-integers true :string-numbers false)) returns the value of (json:load-bytes b :typed true), and rejects the same inputs.

json:use-exact-integers

function: (json:use-exact-integers bool)

Sets the default exact-integers mode for the JSON serializer. When true, a JSON number written as an integer is parsed as an int holding its exact value instead of a float, and an integer too large for an int raises json:integer-range-error instead of silently rounding. Numbers written with a fraction or an exponent are unaffected. When false (the default) every JSON number is parsed as a float, so integers above 2^53 are rounded without warning. Affects all load functions that don't explicitly pass :exact-integers. Returns nil.

json:use-string-numbers

function: (json:use-string-numbers bool)

Sets the default string-numbers mode for the JSON serializer. When true, numbers are serialized as JSON strings and JSON numbers are parsed as strings. Affects plain dump/load calls that don't explicitly pass :string-numbers. Canonical dumping and typed dump/load ignore this default. Returns nil.

lisp

The core ELPS language package. Provides fundamental data types, control flow, function and macro definition, package management, error handling, collections, I/O, and the type system.

*

function: (* &rest x)

Returns the product of all arguments, or 1 with no arguments. Returns int if all args are ints; otherwise converts all args to float before multiplying. Integer arithmetic wraps on overflow.

+

function: (+ &rest x)

Returns the sum of all arguments, or 0 with no arguments. Returns int if all args are ints; otherwise float.

-

function: (- &rest x)

With one argument, returns its negation. With two or more, subtracts subsequent arguments from the first. Returns 0 with no arguments.

/

function: (/ &rest x)

With one argument, returns 1/x. With two or more, divides the first by all subsequent. Returns int when all divisions are exact; otherwise float. Division by zero returns IEEE infinity or NaN, not an error: (/ 1 0) is +Inf and (/ 0.0 0.0) is NaN. Guard count against zero before computing (/ total count).

<

function: (< a b)

Returns true if a < b. Accepts ints and floats.

<=

function: (<= a b)

Returns true if a <= b. Accepts ints and floats.

=

function: (= a b)

Returns true if numeric values a and b are equal.

>

function: (> a b)

Returns true if a > b. Accepts ints and floats.

>=

function: (>= a b)

Returns true if a >= b. Accepts ints and floats.

all?

function: (all? predicate seq)

Returns true if predicate returns truthy for every element in seq. Returns true for an empty sequence. Short-circuits on the first falsey result. Predicate must be a regular function and receives each element as data without evaluation.

and

operator: (and &rest expr)

Short-circuit logical conjunction. Evaluates arguments left to right and returns the first falsey value. If all arguments are truthy, returns the last value. Returns true with no arguments. The final argument preserves tail position if it is reached.

any?

function: (any? predicate seq)

Returns the first truthy result of applying predicate to elements of seq, or false if none match. Short-circuits on the first truthy result. Predicate must be a regular function and receives each element as data without evaluation.

append

function: (append type-specifier vec &rest values)

Returns a new sequence with values appended to vec. The type-specifier ('list, 'vector, or 'bytes) determines the return type. Does not mutate vec and never shares top-level storage with it, so appending to the same source twice yields independent results. This also applies when no values are added. Nested values remain shared. This costs a copy, making append O(n); use append! to accumulate in a loop. (append 'vector ...) over a non-empty quoted program literal raises the catchable modify-literal-error condition -- append to (copy lit) instead.

append!

function: (append! vec &rest values)

Appends values to vec, mutating it in place. Returns the modified vector. When the values do not fit in vec's capacity, the capacity grows to max(2c, n, 4) for capacity c and new length n, on every platform; a new vector's capacity is its length.

append-bytes

function: (append-bytes bytes byte-sequence)

Returns new bytes with byte-sequence appended. The byte-sequence can be a string, bytes, or list of integers. Does not mutate bytes and never shares storage with it; use append-bytes! to accumulate in a loop.

append-bytes!

function: (append-bytes! bytes values)

Appends values to bytes, mutating it in place. Values can be a string, bytes, or list of integers. Returns the modified bytes.

apply

function: (apply fun &rest args)

Calls fun with arguments formed by appending the last argument (which must be a list) to any preceding arguments. For example, (apply f 1 2 '(3 4)) calls f with arguments 1 2 3 4. fun may be a function value or a quoted symbol resolved in the global package environment.

aref

function: (aref a &rest indices)

Returns the element at the given indices in an array. Multiple indices access multi-dimensional arrays.

array?

function: (array? expr)

Returns true if expr is an array, false otherwise.

assert

operator: (assert expr &rest message-format-args)

Evaluates the test expression exactly once and signals an error if the result is falsey. An optional message expression and formatting arguments, evaluated only on the failure path, customize the error message using {} placeholders. The message must produce a string and is evaluated before the formatting arguments.

assoc

function: (assoc map key value)

Returns a new sorted-map with key set to value, without modifying the original. If map is nil, creates a new map. Keys must be ints, strings or symbols. A string and a symbol with the same name are interchangeable, and last write wins for key spelling and value; an int is never the same key as a string or symbol.

assoc!

function: (assoc! map key value)

Sets key to value in map, mutating it in place, and returns the modified map. Keys must be ints, strings or symbols. Last write wins for key spelling and value; JSON-decoded maps always retain string keys, using a symbol's name when supplied.

benchmark

operator: (benchmark name args &rest exprs)

Defines a named benchmark. name must be a string. args is a list containing a single symbol that receives the iteration count. The body should use dotimes or similar to run the benchmarked code count times. Prefer benchmark-simple for simple cases. Like test, benchmark is only available while running tests.

benchmark-simple

macro: (benchmark-simple name &rest exprs)

Defines a simple benchmark that runs exprs repeatedly. Expands to (benchmark name (count) (dotimes (_ count) exprs...)). The iteration count is provided by the benchmark harness.

bool?

function: (bool? expr)

Returns true if expr is a boolean (true or false), false otherwise.

builtin

function: (builtin name)

Returns the builtin registered as name, a quoted qualified symbol such as 'math:floor, whatever that name is bound to now. Rebinding, shadowing or set never change the result. Raises an error when name is not a qualified symbol, when no builtin is registered under it (a defun is not registered), or when its package does not export it; the last two raise the same error. Never returns (). One call costs one step plus one per started 64 exports of the package: look a builtin up once at load scope and reuse the value.

builtin-name

function: (builtin-name value)

Returns "PKG:NAME", a string, when value is the builtin registered as PKG:NAME, whatever that name is bound to now. Returns () for every other value: a lambda, a builtin no registration created (such as a schema validator), a builtin a later registration of its name replaced, a native and a non-function. The answer comes from the registration, never from how the function prints.

bytes?

function: (bytes? expr)

Returns true if expr is a bytes value, false otherwise.

car

function: (car lis)

Returns the first element of a list, or nil if empty.

cdr

function: (cdr lis)

Returns a list of all elements except the first, or nil if the list has fewer than two elements. Like slice, the result is a view sharing elements with lis.

compose

function: (compose f g)

Returns a new function that applies g to its arguments, then applies f to the result. (compose f g) is equivalent to (lambda (...) (f (g ...))).

concat

function: (concat type-specifier &rest args)

Concatenates sequences into one of the specified type. Accepts 'list, 'vector, 'string, or 'bytes as type-specifier.

cond

operator: (cond &rest branch)

Multi-way conditional. Each branch is a clause (test &rest body). Clauses are evaluated in order: for the first truthy test, the body forms are evaluated and the last value returned. Use else or :else as the test in the final clause to match unconditionally; either spelling in a non-final clause raises an error when reached. Returns () if no clause matches or the matching clause has no body.

condition-is?

function: (condition-is? condition ancestor)

Returns true when condition is ancestor or one of its descendants, walking the parents define-condition and elps declare, as Go's errors.Is does. Both arguments are symbols or strings, such as the condition symbol a handler-bind handler receives. Every condition is a 'condition, internal-panic included, though a handler-bind binding for 'condition never catches a recovered Go panic: condition-is? sees only the name.

cons

function: (cons head tail)

Returns a new list with head prepended to the list tail.

copy

function: (copy value)

Returns a deep copy of value that shares no storage with it: lists, vectors, sorted-maps and bytes are rebuilt with fresh backing, recursively, so mutating the copy at any depth cannot be observed through the original. Function values are shared by reference, not copied: a lambda carried into the copy still reads and writes the bindings it captured, so calling one can be observed through the original. Native values are also shared by reference, unless the Go payload declares its own clone protocol (lisp.NativeCloner), in which case the copy holds an independent clone of the payload. Strings and numbers are immutable values. Sharing between values inside the input is preserved in the copy, including cycles; sharing of a backing array between distinct values -- what cdr, rest and slice produce -- is not. Use copy to take ownership of data whose provenance you do not control: the result is always mutable, even when the input is (or came from) a quoted program literal. Raises an ordinary error if a value walk exceeds 1000000 levels (or the configured WithMaxValueDepth setting).

curry-function

macro: (curry-function fun &rest args)

Returns a new function that calls fun with args prepended to any additional arguments supplied at call time. Equivalent to (lambda (&rest rest) (apply fun arg1 arg2 ... rest)).

debug-print

function: (debug-print &rest args)

Prints all arguments to stderr followed by a newline. Returns nil. Nested values deeper than 1024 levels render as #<depth-limit>; cycles render as #<cycle>. Shared DAGs render in full up to the runtime output/work limit; exceeding it raises an allocation error. Rendering honours context cancellation.

debug-stack

function: (debug-stack)

Prints the current call stack to stderr for debugging. Returns nil.

default

operator: (default value fallback)

Nil coalescing. Evaluates value exactly once; if it is not nil it is returned and fallback is not evaluated. Otherwise fallback is evaluated (in tail position) and its value returned. Note that only () counts as missing: false, 0 and "" are returned as-is. A package may still define or import its own default, which shadows this operator there.

defconst

macro: (defconst name value &rest docstring)

Defines an exported, documented constant. Binds value to name in the current package and exports it. Optional trailing strings set the documentation (concatenated; empty strings produce paragraph breaks). Equivalent to (set 'name value docs...) followed by (export 'name).

define-condition

function: (define-condition child parent)

Makes condition parent the parent of condition child, so a handler-bind binding for parent, or for an ancestor of parent, catches child, and condition-is? sees the link. Both arguments are symbols or strings. A condition has at most one parent, and gets it before its children, so define a hierarchy from the root down: defining the parent it already has does nothing, and any other parent is an error. Giving a parent to a condition that has children (error has argument-error, match-error and record-error), a chain more than 64 deep, or a definition that names condition or internal-panic is an error. The hierarchy belongs to the runtime: a template publishes it and every VM forked from it starts with it. A definition does not change how an error renders. Returns child as a symbol.

defmacro

macro: (defmacro name formals &rest expr)

Defines a named macro in the current package. The body receives unevaluated forms and must return a form to be evaluated at the call site. Use quasiquote/unquote to construct the expansion. An optional leading string in the body serves as a docstring. Malformed lambda lists and duplicate parameter names are errors at creation; see lambda for the parameter-list rules. The lisp package is sealed after initialization; defining a name there signals: cannot rebind lisp package binding: name. Unqualified builtin shadowing in your own package remains legal.

deftype

macro: (deftype name constructor-formals &rest constructor-exprs)

Defines a tagged type constructor bound to name in the current package. The formals and body define a constructor function that computes user data for new instances created with (new name ...). Returns the qualified type symbol.

defun

macro: (defun name formals &rest expr)

Defines a named function in the current package. Malformed lambda lists and duplicate parameter names are errors at creation; see lambda for parameter-list and duplicate keyword rules. The lisp package is sealed after initialization; defining a name there signals: cannot rebind lisp package binding: name. Unqualified builtin shadowing in your own package remains legal.

dissoc

function: (dissoc map key)

Returns a new sorted-map with key removed, without modifying the original.

dissoc!

function: (dissoc! map key)

Removes key from map, mutating it in place, and returns the modified map. String and symbol keys with the same name are interchangeable, including in JSON-decoded maps.

dotimes

operator: (dotimes control-sequence &rest exprs)

Iterates a body a fixed number of times. The control-sequence is (symbol count [result]) where count evaluates to an integer. The body is evaluated count times with symbol bound to 0, 1, ..., count-1. Returns the result expression (or () if omitted).

empty?

function: (empty? seq)

Returns true if the sequence has zero elements, false otherwise.

equal?

function: (equal? a b)

Returns true if a and b are structurally equal, performing deep comparison across all value types. Bytes values compare by content, and a reader quote (''a) by its quoted value. Sorted-map keys compare by name, matching how get and key? identify them, so a map keyed by 'a is equal? to a map keyed by "a". Raises an ordinary depth error if comparison exceeds the configured value depth (default 1000000).

error

function: (error condition &rest args)

Signals an error with the given condition name (a symbol) and optional data arguments. The condition can be caught by handler-bind. Rendering error data and stack-trace messages honours the runtime output/work limit and cancellation, using #<truncated> on exhaustion without changing the condition data.

error-message

function: (error-message)

Returns the message of the error being handled by handler-bind, as a string, with any context added by (rethrow :context ...). It is the text an uncaught error renders after its condition. Can only be called from within a handler-bind handler.

error-stack

function: (error-stack)

Returns the call stack recorded when the error being handled by handler-bind was raised, as a list of sorted-maps ordered innermost frame first. Each map has the string key "function" (the package-qualified function name) and, when the frame has a source location, "file", "line" and "column" of the call that entered it; "file" is the source name the library reported (a bare file name for the built-in libraries), not a host path. Can only be called from within a handler-bind handler. Charges one evaluation step per started 64 frames.

eval

function: (eval expr)

Evaluates expr in the current environment and returns the result. Quoted values are unquoted one level before evaluation.

export

function: (export &rest symbol)

Marks symbols as exported from the current package, making them available to other packages via use-package. Accepts unqualified symbols, strings, or nested lists of these; qualified names are rejected. All arguments are validated before exporting anything. Symbols may be defined later, but must be bound when use-package imports them. Cannot add exports to the sealed lisp package. Returns nil.

expr

operator: (expr pattern)

Creates an anonymous function from a template using positional placeholders: % for a single argument, %1 %2 etc. for numbered arguments, %&rest for variadic arguments. Returns a lambda whose formals are derived from the placeholders.

first

function: (first seq)

Returns the first element of a sequence (list or vector), or nil if empty.

flet

operator: (flet bindings &rest expr)

Binds locally-scoped named functions and evaluates the body. Each binding has the form (name formals &rest body). Functions cannot reference each other or recurse by name. Use labels for mutual or self-recursion. Malformed lambda lists and duplicate parameter names are errors at creation. Duplicate function names are legal (the last binding wins), but lint warns. Returns the last body value.

flip

function: (flip binary-function)

Returns a new function that calls binary-function with its two arguments swapped.

float?

function: (float? expr)

Returns true if expr is a float, false otherwise.

foldl

function: (foldl fn z seq)

Left-folds seq with binary function fn starting from accumulator z. Calls (fn acc elem) for each element left to right, threading the result. Returns z if seq is empty.

foldr

function: (foldr fn z seq)

Right-folds seq with binary function fn starting from accumulator z. Calls (fn elem acc) for each element right to left, threading the result. Returns z if seq is empty.

format-string

function: (format-string format &rest values)

Returns a string by replacing placeholders in the format string with corresponding values. Use {} for sequential substitution or {0}, {1}, etc. for positional. Strings are interpolated without quotes. Use {{ and }} for literal braces. Cannot mix sequential and positional styles. Whitespace around positional indices is accepted: { 0 } means {0}. Surplus values are ignored; a placeholder without a corresponding value raises an error. Nested values deeper than 1024 levels render as #<depth-limit>, however deeply the value itself nests: printing a value is never a depth error, and debug-print agrees. Cycles render as #<cycle>. Shared DAGs render in full up to the runtime output/work limit; exceeding it raises an allocation error. Rendering honours context cancellation.

funcall

function: (funcall fun &rest args)

Calls fun with the given args and returns the result. fun may be a function value or a quoted symbol resolved in the global package environment. Cannot be used with special operators or macros.

function

operator: (function name)

Returns the function bound to the given symbol without calling it. This is the operator behind the #' reader macro. Signals an error if the symbol is not bound to a function.

gensym

function: (gensym)

Returns a new symbol named genNNNNNNNN, unique within the runtime: each call takes the next number from a per-runtime counter. Useful in macros to avoid variable name collisions. The result is an ordinary symbol, not an uninterned one, so it is equal? to a symbol spelled the same way; do not give your own variables names of that form.

get

function: (get map key)

Returns the value associated with key in a sorted-map, or nil if the key is not present or map is nil. String and symbol keys with the same name are interchangeable, including in JSON-decoded maps.

get-default

macro: (get-default map key default)

Looks up key in a sorted-map, returning the associated value if found. If the key is not present or map is nil, evaluates and returns default. String and symbol keys with the same name are interchangeable, including in JSON-decoded maps. The default expression is evaluated only when needed (lazy evaluation).

handler-bind

operator: (handler-bind bindings &rest forms)

Evaluates body forms with condition handlers in scope. The first argument is a list of (condition-type handler-fn) pairs. If a body form signals an error matching a condition type, the handler is called with the condition name and error data as values, without evaluating the data. Copying condition data beyond 1000000 levels (or the configured WithMaxValueDepth setting) raises an ordinary depth error that propagates to an outer handler: the copy failure keeps its own condition name rather than being reclassified. Go errors supply message strings. Source parse errors retain their parser condition names. An error raised by a handler propagates past this handler-bind and can be caught by an outer one. Handlers must be regular functions. A condition type also matches its descendants: 'error matches 'argument-error, which Go argument helpers raise for a bad argument, and define-condition adds parents. When several bindings match, the most specific one runs: the binding for the condition itself, else the one for its nearest ancestor, with 'condition last; bindings for the same type run in source order. Use the symbol 'condition to match any error. The internal-panic condition — a Go panic recovered from host code — is excluded from 'condition' and must be named explicitly to be intercepted. Returns () when there are no body forms, after validating the bindings. Like with-cleanup, blocks tail-call optimization across this form, even with empty bindings. Keep recursion outside the handler and handle each iteration's work inside it.

help

operator: (help var-name)

Prints documentation for the given variable name, as the calling code sees it: a lexical binding, a name in the current package, or a qualified name. Functions have their signature and any docstring rendered. Other variables have their types and current values printed. The name is not evaluated.

identity

function: (identity value)

Returns its argument unchanged.

if

operator: (if condition then else)

Conditional branch. Evaluates condition; if truthy, evaluates and returns then, otherwise evaluates and returns else. All three arguments are required. Only one branch is evaluated.

ignore-errors

operator: (ignore-errors &rest exprs)

Evaluates body forms sequentially. If any form signals an error, evaluation stops and () is returned instead of propagating the error. Returns the last value if no error occurs. The internal-panic condition is not suppressed: a Go panic recovered from host code signals a defect in that code, so it propagates.

in-package

function: (in-package package-name &rest docstring)

Switches the current package to package-name, creating it if it does not exist. The name must be a symbol or string spelling a non-empty symbol identifier, without colons or a keyword prefix. Optional trailing strings set the package documentation. All arguments are validated before creating or switching packages. This is an ordinary evaluated form: calling it from a helper can change the caller's package for subsequent forms. Only loads guarantee automatic restoration of the caller's package. Returns nil.

insert-index

function: (insert-index type-specifier seq index item)

Returns a new sequence with item inserted at the given index. The type-specifier ('list or 'vector) determines the return type.

insert-sorted

function: (insert-sorted type-specifier list predicate item &rest key-fun)

Returns a new sequence with item inserted at its sorted position according to predicate. An optional key-fun extracts comparison keys from elements. Predicate and key-fun must be regular functions; elements and keys are passed as data without evaluation.

int?

function: (int? expr)

Returns true if expr is an integer, false otherwise.

key?

function: (key? map key)

Returns true if key exists in the sorted-map, false otherwise. String and symbol keys with the same name are interchangeable, including in JSON-decoded maps.

keys

function: (keys map)

Returns a list of all keys in a sorted-map in sorted order. Key spelling follows the last write; JSON-decoded maps always return string keys.

labels

operator: (labels bindings &rest expr)

Binds locally-scoped named functions and evaluates the body. Each binding has the form (name formals &rest body). Unlike flet, all functions share the same scope so they may call each other and themselves recursively. Malformed lambda lists and duplicate parameter names are errors at creation. Duplicate function names are legal (the last binding wins), but lint warns. Returns the last body value.

lambda

operator: (lambda formals &rest expr)

Returns an anonymous function. Formals is a list of parameter names that may include &optional, &rest, and &key markers. Malformed lists and duplicate parameter names are errors at creation. Each marker may occur once; &rest must have exactly one final name. Duplicate keyword arguments use the rightmost value, unlike Common Lisp. Parameter names must be symbols; naming true, false, or a keyword is an error at creation. The body expressions are evaluated in order and the last value is returned. A string literal as the first body expression serves as a documentation string.

length

function: (length seq)

Returns the number of elements in a sequence. Accepts lists, vectors, sorted-maps, strings, and bytes.

let

operator: (let bindings &rest expr)

Creates local variable bindings evaluated in parallel. All value expressions are evaluated in the enclosing scope before any bindings are established. The first argument is a list of [symbol value] pairs. In place of the symbol a binding may give a match pattern, such as [(list a b) v]: the value must match it, and its names are bound. A value that does not match raises match-error. Duplicate names are legal (the last binding wins), but lint warns; use let* for sequential rebinding. Returns the last body value.

let*

operator: (let* bindings &rest expr)

Creates local variable bindings evaluated sequentially, so each binding can refer to previously bound symbols. Repeated names are legal sequential rebinding and do not produce duplicate-binding lint warnings. The first argument is a list of [symbol value] pairs. In place of the symbol a binding may give a match pattern, such as [(list a b) v]: the value must match it, and its names are bound. A value that does not match raises match-error. Returns the last body value.

list

function: (list &rest args)

Returns a new list containing all the given arguments.

list?

function: (list? expr)

Returns true if expr is a list (including nil), false otherwise.

load-bytes

function: (load-bytes source-code &key name)

Parses and evaluates source-code (a bytes value) as ELPS source. The optional :name keyword provides a label for error messages. Returns the result of the last evaluated expression.

load-file

function: (load-file source-location)

Loads and evaluates the ELPS source file at source-location. File access follows the runtime's source library policy. In elps run, debug, and repl, loads are confined to --root-dir (default: working directory) at open time. Relative symlinks within the root are allowed; escaping paths and absolute symlinks return ordinary errors. Returns the result of the last evaluated expression.

load-string

function: (load-string source-code &key name)

Parses and evaluates source-code (a string) as ELPS source. The optional :name keyword provides a label for error messages. Returns the result of the last evaluated expression.

macroexpand

function: (macroexpand quoted-form)

Repeatedly expands the macro call in quoted-form until the head is no longer a macro. Returns the fully expanded form. Recursive value walks exceeding 1000000 levels raise an ordinary depth error.

macroexpand-1

function: (macroexpand-1 quoted-form)

Performs a single macro expansion step on quoted-form and returns the result. Useful for debugging macro expansion. Recursive value walks exceeding 1000000 levels raise an ordinary depth error.

macroexpand-all

function: (macroexpand-all quoted-form)

Expands every macro call in quoted-form, not just the head: the head is expanded until it is no longer a macro, then each nested form in code position is expanded the same way. Knows the binding shape of every special form, so a local variable or function that shadows a macro name is left alone, macrolet macros are expanded, and quoted data (quote, the non-unquoted parts of quasiquote, condition types) is never entered. defun and defmacro are kept as written with their bodies expanded. The input is not modified. Nesting deeper than the evaluator's nesting limit, or a head that keeps expanding past the macro expansion limit, is an error.

macrolet

operator: (macrolet bindings &rest expr)

Binds locally-scoped macros and evaluates the body. Each binding has the form (name formals &rest body). The macros do not share scope with each other. Malformed lambda lists and duplicate parameter names are errors at creation. Returns the last body value.

make-sequence

function: (make-sequence start stop &rest step)

Returns a list of numbers from start (inclusive) to stop (exclusive), incrementing by step (default 1).

map

function: (map type-specifier fn seq)

Returns a sequence containing values returned by applying unary function fn to elements of seq in order. The type-specifier ('list or 'vector) determines the return type. fn may be a function value or a quoted symbol resolved in the global package environment.

match

operator: (match value &rest clause)

Pattern match. Evaluates value, then tries each clause (pattern [:when guard] body...) in order. For the first pattern that matches, and whose guard is truthy, the body forms are evaluated with the names the pattern binds, and the last value returned. A final (:else body...) clause matches anything. Returns () if no clause matches. Patterns: _ matches anything; a symbol matches anything and binds it; a number, string, keyword, true, false, () or 'sym matches an equal? value; (quote datum) matches an equal? datum; (list p... &rest r) matches a list; (vector p... &rest r) matches a vector, a 1-D array; with &rest, r gets a new list or vector of the remaining items; (sorted-map key p ...) matches a map with those keys; [name T] matches a value of type T; (T :field p ...) matches a value of type T with those fields. T is evaluated each time it is tried. Type patterns need a type library such as package s. A guard that is false goes on to the next clause; an error in a guard, a type expression or a pattern stops the match. A quoted list in a pattern is always [name T]; match a literal list with (list 'a 'b). A pattern that binds a name twice is an error.

max

function: (max real &rest rest)

Returns the largest of the given numeric arguments. Returns NaN if any argument is NaN, regardless of position. All-int arguments produce an int result.

min

function: (min real &rest rest)

Returns the smallest of the given numeric arguments. Returns NaN if any argument is NaN, regardless of position. All-int arguments produce an int result.

mod

function: (mod a b)

Returns the remainder of integer division a mod b. Both arguments must be ints. A zero b raises an error with the message "second argument is zero"; unlike /, mod does not return infinity or NaN for a zero divisor.

new

function: (new type-specifier &rest arguments)

Creates a new instance of the type named by type-specifier, passing additional arguments to the type's constructor.

nil?

function: (nil? expr)

Returns true if expr is nil (the empty list), false otherwise.

not

function: (not expr)

Returns true if expr is falsey (nil or false), false otherwise.

nth

function: (nth seq n)

Returns the element at zero-based index n in a sequence, or nil if n is out of bounds.

number?

function: (number? expr)

Returns true if expr is numeric (int or float), false otherwise.

or

operator: (or &rest expr)

Short-circuit logical disjunction. Evaluates arguments left to right and returns the first truthy value. If no argument is truthy, returns the last value. Returns false with no arguments.

pow

function: (pow a b)

Returns a raised to the power b. Returns int when both args are ints and b >= 0; otherwise returns float. Raises an error containing "integer overflow" if the integer result does not fit int. A zero exponent returns 1, including (pow 0 0).

progn

operator: (progn &rest expr)

Evaluates its body forms sequentially and returns the value of the last form. Returns () if no forms are given.

qualified-symbol

operator: (qualified-symbol symbol)

Returns a quoted package-qualified symbol. If the symbol is already qualified (contains a colon), returns it as-is. Otherwise prepends the current package name (e.g. user:name).

quasiquote

operator: (quasiquote expr)

Returns a quoted template in which (unquote expr) forms are evaluated and spliced in, and (unquote-splicing expr) forms are evaluated and their list elements are spliced in. All other subexpressions remain unevaluated. Raises an ordinary depth error when traversal exceeds 1000000 levels or the configured WithMaxValueDepth setting.

quote

operator: (quote expr)

Returns its argument unevaluated. This is the operator behind the ' prefix syntax.

reject

function: (reject type-specifier predicate seq)

Returns a new sequence containing only elements for which predicate returns falsey. The type-specifier ('list or 'vector) determines the return type.

rest

function: (rest lis)

Returns a list of all elements except the first. Accepts lists and vectors. Returns nil if fewer than two elements. Like slice, the result is a view sharing elements with lis.

rethrow

function: (rethrow &key context)

Re-throws the current error being handled by handler-bind, preserving the original stack trace. Can only be called from within a handler-bind handler. Use this instead of (apply error condition args) when you want to perform side effects (such as logging) but still propagate the original error unchanged.

With :context, a string, the error is re-thrown with that string and ": " in front of its message, as Go's fmt.Errorf with %w adds context: (rethrow :context (format-string "loading user {}" id)) turns "no user 42" into "loading user 42: no user 42". The condition, data and stack are unchanged, so every handler that matched the error still matches it. Each wrap puts its context in front of the earlier ones. An empty string or () re-throws the error unchanged.

reverse

function: (reverse type-specifier seq)

Returns a new sequence with elements in reverse order. The type-specifier ('list or 'vector) determines the return type. seq must be a list or vector; strings are not supported.

search-sorted

function: (search-sorted n predicate)

Returns the smallest index i in [0, n) for which predicate returns true, using binary search. Equivalent to Go's sort.Search. Predicate must be a regular function and receives each probed index as data without evaluation.

second

function: (second seq)

Returns the second element of a sequence (list or vector), or nil if fewer than two elements.

select

function: (select type-specifier predicate seq)

Returns a new sequence containing only elements for which predicate returns truthy. The type-specifier ('list or 'vector) determines the return type.

set

function: (set sym val &rest docstring)

Binds val to the quoted symbol sym in the current package scope, creating or overwriting the binding. Optional trailing strings set the symbol's documentation (concatenated; empty strings produce paragraph breaks). Returns the bound value. This is the primary way to create top-level bindings. Use set! to mutate an existing binding without risk of accidental creation. After initialization, writes to lisp: names or names in package lisp signal an error: cannot rebind lisp package binding: name. Unqualified builtin shadowing in your own package remains legal.

set!

operator: (set! name expr)

Mutates an existing variable binding. Evaluates expr and updates the binding of the quoted symbol name. Signals an error if the symbol is not already bound in any enclosing scope or the current package. Cannot rebind the constants true and false. After initialization, writes to the lisp package signal: cannot rebind lisp package binding: name. Unqualified builtin shadowing in your own package remains legal.

slice

function: (slice type-specifier seq start end)

Returns a subsequence from index start (inclusive) to end (exclusive). Accepts lists, vectors, strings, and bytes. String indices count bytes, so slicing through a rune can produce invalid UTF-8: (slice 'string "José" 0 4) ends with the byte 0xc3. For rune-safe slicing, split with (string:split str ""), slice the resulting list, then join with (string:join pieces ""). For lists, vectors and bytes the result is a view sharing elements with seq: appending to it cannot disturb seq, but sorting it in place also sorts that region of seq. Use concat to take a copy. String slices are always independent. A vector is mutable, so (slice 'vector ...) over a non-empty quoted program literal raises the catchable modify-literal-error condition -- slice (copy lit) instead.

sorted-map

function: (sorted-map &rest args)

Creates a new sorted-map from alternating key-value pairs. For example, (sorted-map :a 1 :b 2). Keys must be integers, strings or symbols; other types are unhashable. Integer keys come first, in numeric order, then string and symbol keys in sorted order. An integer key is distinct from the string or symbol spelling the same digits. String and symbol keys with the same name are interchangeable; last write wins for key spelling and value.

sorted-map?

function: (sorted-map? expr)

Returns true if expr is a sorted-map, false otherwise.

stable-sort

function: (stable-sort less-predicate list &rest key-fun)

Sorts list using the binary less-predicate and returns the sorted list. The sort is stable. An optional key-fun extracts comparison keys from elements. Both callbacks must be regular functions; elements and keys are passed as data without evaluation. A mutable list is sorted in place, so sorting a slice view also sorts that region of its source; sort (concat 'list x) when x is a view you do not own. A quoted program literal is never modified: sorting a non-empty literal (or a view sharing its storage) raises the catchable modify-literal-error condition -- sort (copy lit) instead.

string<

function: (string< a b)

Returns true if string a is lexicographically < string b.

string<=

function: (string<= a b)

Returns true if string a is lexicographically <= string b.

string=

function: (string= a b)

Returns true if strings a and b are equal.

string>

function: (string> a b)

Returns true if string a is lexicographically > string b.

string>=

function: (string>= a b)

Returns true if string a is lexicographically >= string b.

string?

function: (string? expr)

Returns true if expr is a string, false otherwise.

symbol=

function: (symbol= a b)

Returns true if symbols a and b are equal.

symbol?

function: (symbol? expr)

Returns true if expr is a symbol, false otherwise.

tagged-value?

function: (tagged-value? value)

Returns true if value is a tagged value (user-defined type instance), false otherwise.

test

operator: (test name &rest exprs)

Defines a named test case. name must be a string. The body expressions are wrapped in a lambda, written in the current package like a defun body, and registered with the test suite for later execution. Use the testing package's assert macros inside the body to check conditions. Tests can only be defined while running tests: outside a test runner there is no test suite and test signals an error.

test-let

macro: (test-let name bindings &rest exprs)

Defines a named test with local let bindings. Expands to (test name (let (bindings) exprs...)). The bindings use parallel binding (let) semantics.

test-let*

macro: (test-let* name bindings &rest exprs)

Defines a named test with local let* bindings. Like test-let but uses sequential binding (let*) semantics, so later bindings can reference earlier ones.

thread-first

operator: (thread-first value &rest exprs)

Threads a value through a series of function calls by inserting it as the first argument after the function name in each form. Evaluates the initial value once, before any step's function or arguments, then passes each result as data to the next step. A macro or special operator step gets the value as a quoted datum, as in (step 'value args...). Returns the result of the final form.

thread-last

operator: (thread-last value &rest exprs)

Threads a value through a series of function calls by inserting it as the last argument in each form. Evaluates the initial value once, before any step's function or arguments, then passes each result as data to the next step. A macro or special operator step gets the value as a quoted datum, as in (step args... 'value). Returns the result of the final form.

to-bytes

function: (to-bytes value)

Converts value to a bytes value. Accepts strings (encoded as UTF-8) and bytes (returned as-is).

to-float

function: (to-float value)

Converts value to a float. Accepts strings (parsed), floats (returned as-is), and integers (widened).

to-int

function: (to-int value)

Converts value to an integer. Accepts strings (parsed as decimal), integers (returned as-is), and floats (truncated toward zero). Non-finite floats and truncated values outside the int range return an error.

to-string

function: (to-string value)

Converts value to its string representation. Accepts strings, symbols, bytes, integers, and floats.

trace

macro: (trace expr &optional message)

Evaluates expr, prints the result to stderr prefixed by message (default "TRACE") using debug-print, then returns the result. The expression is evaluated exactly once. Useful for debugging without altering control flow.

true?

function: (true? expr)

Returns true if expr is truthy (not nil and not false), false otherwise. Useful as an explicit boolean conversion.

type

function: (type value)

Returns a symbol naming the type of value (e.g. 'int, 'float, 'string, 'list, 'sorted-map, 'array, 'bytes, 'fun).

type?

function: (type? type-specifier value)

Returns true if value matches the type-specifier symbol. Also accepts a tagged typedef for user-defined types.

unless

operator: (unless condition &rest body)

Inverse one-armed conditional. Evaluates condition; if falsey, evaluates the body forms in order and returns the last value (() when there is no body). If condition is truthy the body is not evaluated and () is returned. The last body form is in tail position. Equivalent to (if (not condition) (progn body...) ()). A package may still define or import its own unless, which shadows this operator there.

unpack

function: (unpack f lis)

Calls f with the elements of lis as individual arguments. Equivalent to (apply f lis).

use-package

function: (use-package &rest package-name)

Imports all exported symbols from the named packages into the current package. Names must be symbols or strings spelling non-empty symbol identifiers, without colons or a keyword prefix. An export that is still unbound causes an error naming its package and symbol. Cannot import bindings into the sealed lisp package. Returns nil.

user-data

function: (user-data value)

Returns the user data associated with a tagged value.

vector

function: (vector &rest args)

Returns a new one-dimensional array (vector) containing all the given arguments.

vector?

function: (vector? expr)

Returns true if expr is a one-dimensional array (vector), false otherwise.

when

operator: (when condition &rest body)

One-armed conditional. Evaluates condition; if truthy, evaluates the body forms in order and returns the last value (() when there is no body). If condition is falsey the body is not evaluated and () is returned. The last body form is in tail position. Equivalent to (if condition (progn body...) ()) without a macro expansion. A package may still define or import its own when, which shadows this operator there.

while

operator: (while condition &rest body)

Loop. Evaluates condition; while it is truthy, evaluates the body forms in order and then re-evaluates condition. Always returns (). An error in condition or body stops the loop and propagates. Each turn counts against the evaluation limits: the step limit and context deadline when configured, and the tail-iteration limit (WithMaxTailIterations, on by default) as a runaway-loop backstop, so a while that never terminates stops as the equivalent tail-recursive loop would. The body introduces no new scope. A package may still define or import its own while, which shadows this operator there.

with-cleanup

operator: (with-cleanup cleanup &rest body)

Evaluates the body forms, then always evaluates the cleanup forms -- whether the body returned normally or signalled. The first argument is a list of cleanup forms. Returns the last body value; cleanup values are discarded. Unlike handler-bind and ignore-errors it does not catch: an error keeps propagating after the cleanup has run. If a cleanup form itself signals, that error replaces the outcome already in flight and the remaining cleanup forms are skipped -- except over an internal-panic, which always wins and is never masked.

zip

function: (zip type-specifier list &rest lists)

Returns a sequence of sequences, where the i-th inner sequence contains the i-th element from each input list. Truncated to the shortest input.

math

Mathematical functions: trigonometry, logarithms, exponents, absolute value, floor/ceiling, and mathematical constants (pi, inf).

math:-inf

variable

Negative infinity (IEEE 754).

math:abs

function: (math:abs number)

Returns the absolute value of number. Preserves the type: an int argument returns an int, a float returns a float. Returns an error on integer overflow (min-int).

math:acos

function: (math:acos radians)

Returns the arccosine (inverse cosine) in radians as a float. The argument must be in the range [-1, 1].

math:acosh

function: (math:acosh radians)

Returns the inverse hyperbolic cosine as a float. The argument must be >= 1.

math:asin

function: (math:asin radians)

Returns the arcsine (inverse sine) in radians as a float. The argument must be in the range [-1, 1].

math:asinh

function: (math:asinh radians)

Returns the inverse hyperbolic sine as a float.

math:atan

function: (math:atan radians &optional quotient)

Returns the arctangent as a float. With one argument, returns atan(radians). With two arguments, returns atan2(radians, quotient), computing the angle in the correct quadrant.

math:atanh

function: (math:atanh radians)

Returns the inverse hyperbolic tangent as a float. The argument must be in the range (-1, 1).

math:ceil

function: (math:ceil number)

Returns the smallest float not less than number (rounds toward positive infinity). Integers are returned unchanged. The result is always a float for float input.

math:cos

function: (math:cos radians)

Returns the cosine of radians as a float.

math:cosh

function: (math:cosh radians)

Returns the hyperbolic cosine of radians as a float.

math:exp

function: (math:exp number)

Returns e raised to the power of number (e^x) as a float. Accepts int or float arguments.

math:floor

function: (math:floor number)

Returns the largest float not greater than number (rounds toward negative infinity). Integers are returned unchanged. The result is always a float for float input.

math:inf

variable

Positive infinity (IEEE 754).

math:ln

function: (math:ln number)

Returns the natural logarithm (base e) of number as a float. Accepts int or float arguments.

math:log

function: (math:log base number)

Returns the logarithm of number in the given base as a float. Both arguments must be numbers. Computed as ln(number)/ln(base).

math:nan?

function: (math:nan? number)

Returns true if number is IEEE 754 NaN (not-a-number). Integers always return false. Returns an error if the argument is not a number.

math:pi

variable

The ratio of a circle's circumference to its diameter (3.14159...).

math:sin

function: (math:sin radians)

Returns the sine of radians as a float.

math:sinh

function: (math:sinh radians)

Returns the hyperbolic sine of radians as a float.

math:sqrt

function: (math:sqrt number)

Returns the square root of number as a float. Accepts int or float arguments.

math:tan

function: (math:tan radians)

Returns the tangent of radians as a float.

math:tanh

function: (math:tanh radians)

Returns the hyperbolic tangent of radians as a float.

regexp

Regular expression compilation and matching using Go RE2 syntax.

regexp:regexp-compile

function: (regexp:regexp-compile pattern)

Compiles a regular expression pattern string and returns a native regexp object. Uses Go's RE2 syntax. Returns an error with condition 'invalid-regexp-pattern' if the pattern is invalid.

regexp:regexp-match?

function: (regexp:regexp-match? re text)

Returns true if the regexp matches text. re may be a compiled regexp or a pattern string (compiled on each call). text may be a string or bytes value.

regexp:regexp-pattern

function: (regexp:regexp-pattern re)

Returns the pattern string of a compiled regexp object. The argument may be a compiled regexp or a string (which will be compiled first).

regexp:regexp?

function: (regexp:regexp? value)

Returns true if value is a compiled regular expression (created by regexp-compile). Returns false for all other types.

s

Schema validation: define typed validators with constraints and check values against them at runtime. Validators compose to describe complex data structures.

s:%add-method

function: (s:%add-method type name fn replace &optional sig)

The function s:defmethod expands to. Do not call it directly. It raises record-error after the load ends.

s:%make-interface

function: (s:%make-interface name methods &optional embed)

The function s:make-interface expands to. Do not call it directly.

s:%make-record

function: (s:%make-record name fields methods check marker &optional sigs implements)

The function s:make-record expands to. Do not call it directly.

s:any

variable

Type name matching any value type (no type constraint).

s:array

variable

Type name for array values.

s:as

function: (s:as value type)

Returns value if it passes type, as s:is? checks it, and raises the check's error if not. Use it to check a value in an expression: (let ((o (s:as x order))) ...).

s:bool

variable

Type name for boolean values: the symbols true and false, not the strings "true" and "false".

s:bytes

variable

Type name for byte-sequence values.

s:defmethod

macro: (s:defmethod type name formals &rest body)

Adds a method to a record type that the same package defined: (s:defmethod type name (recv args...) body...). The first formal, recv, is the object, and a formal after it may be [name type], as in s:method. It refuses a name that is a field of the type, and a name the type already has unless the body starts with :replace true. It raises record-error after the load ends, as in a transaction or a test body: write it at the top level of a file, so it runs at load. Checks of the method's form and of the type come first.

s:describe

function: (s:describe validator)

Returns the definition of a validator as a sorted map: its op ("type", "has-key", "in", ...), and where they apply its name, base type, key, literal values and the definitions of the constraints it holds. Lint, the LSP and checks against other type systems read a schema back through it. A validator built in Go with NewValidator describes itself as "opaque".

s:error

variable

Type name for error values.

s:fields

function: (s:fields obj)

Returns a copy of a record object's fields as a sorted map. Store this map, not the object, in a ledger or other plain data; pass it back to the type to rebuild the object.

s:float

variable

Type name for floating-point values.

s:fun

variable

Type name for function values.

s:gt

function: (s:gt allowed-value)

Returns a constraint that checks if the input is strictly greater than allowed-value. Works with numeric types. NaN never satisfies a numeric constraint, and a NaN allowed-value is an error.

s:gte

function: (s:gte allowed-value)

Returns a constraint that checks if the input is greater than or equal to allowed-value. Works with numeric types. NaN never satisfies a numeric constraint, and a NaN allowed-value is an error.

s:has-key

function: (s:has-key key &rest allowed-types)

Returns a constraint for sorted-maps that checks the map has the specified key and its value matches one of the allowed types. key is a string. Returns the key name on success (used by no-other-keys).

s:in

function: (s:in &rest allowed-values)

Returns a constraint that checks if the input is equal to one of the allowed values. Useful for creating enum-like types. Example: (s:in "red" "green" "blue").

s:int

variable

Type name for integer values.

s:is-false

function: (s:is-false)

Returns a constraint that checks if the input is the boolean false symbol. The string "false" does not qualify.

s:is-falsy

function: (s:is-falsy)

Returns a constraint that checks if the input is falsy (the logical negation of is-truthy).

s:is-true

function: (s:is-true)

Returns a constraint that checks if the input is the boolean true symbol. The string "true" does not qualify.

s:is-truthy

function: (s:is-truthy)

Returns a constraint that checks if the input is truthy. Truthy values include: true, non-empty strings (not "false"), non-empty arrays/maps/bytes, and positive numbers. A map is non-empty when it has an entry, and an array when it has an element (a zero-dimensional array has one).

s:is?

function: (s:is? value type)

Returns true if value passes type, and false if not. type is what a typed formal takes: a built-in type name (s:int), a record type (the full check), (s:ref T), an interface or another validator. Only wrong-type and failed-constraint mean false; any other error, such as a type that is not a type or a condition a :check raises itself, propagates.

s:len

function: (s:len allowed-value)

Returns a constraint that checks if the length of the input equals allowed-value. Works with strings, bytes, and arrays.

s:lengt

function: (s:lengt allowed-value)

Returns a constraint that checks if the length of the input is strictly greater than allowed-value. Works with strings, bytes, and arrays.

s:lengte

function: (s:lengte allowed-value)

Returns a constraint that checks if the length of the input is greater than or equal to allowed-value. Works with strings, bytes, and arrays.

s:lenlt

function: (s:lenlt allowed-value)

Returns a constraint that checks if the length of the input is strictly less than allowed-value. Works with strings, bytes, and arrays.

s:lenlte

function: (s:lenlte allowed-value)

Returns a constraint that checks if the length of the input is less than or equal to allowed-value. Works with strings, bytes, and arrays.

s:list

variable

Type name for list values; () is the empty list. The s:len constraints do not measure a list, so they pass any list.

s:lt

function: (s:lt allowed-value)

Returns a constraint that checks if the input is strictly less than allowed-value. Works with numeric types. NaN never satisfies a numeric constraint, and a NaN allowed-value is an error.

s:lte

function: (s:lte allowed-value)

Returns a constraint that checks if the input is less than or equal to allowed-value. Works with numeric types. NaN never satisfies a numeric constraint, and a NaN allowed-value is an error.

s:make-interface

macro: (s:make-interface name &rest methods)

Defines an interface, a set of methods, and returns it: (s:make-interface "payable" (pay (amount)) (cancel ())). Each method is (name (args...)): its formals after the receiver, with &optional, &rest and &key allowed. A formal may be [name type]; the type documents the method and is not matched. The option :embed (iface...) adds the methods of other interfaces, as a Go interface embeds one; a name may come from two places only with the same arity. A value satisfies the interface when it is a record object whose type has each method, and each method accepts every call the interface allows, as in Go. A field counts as a method that takes no arguments. The interface is a validator: use it as a field type, in s:of, or with s:validate.

s:make-record

macro: (s:make-record name &rest forms)

Defines a record type and returns it. The type is a constructor: (type :field value ...) or (type field-map) builds an object, which is checked against the fields. Each form is a field, (s:has-key "f" ...) or (s:may-have-key "f" ...); a method, (s:method name (recv args...) body...), whose first formal is the object, as a Go method receiver is; the option :check fn, a function of the new object that raises an error to refuse it; or the option :implements (iface...), interfaces the type must satisfy. A method in the form that does not match an interface fails at once; a method that is missing fails at the first construction, so s:defmethod can still add it. Call an object as (obj 'name args...): a method runs, and a field name returns the field. Any other name raises unknown-operation. A method call is atomic: if it raises an error, or :check refuses the object, the fields return to their state before the call. Bind the type with a top-level set: a saved object names that global.

s:make-validator

function: (s:make-validator name type &rest constraints)

Creates and returns a validator function without binding it. name may be a string or a typedef (tagged value). When name is a typedef, the type argument is treated as a constraint on the user-data and "tagged-value" is implied. Bind the result with core set to use it with s:validate, e.g. (set 'title (s:make-validator "title" s:string (s:in "Mr" "Ms" "Dr"))).

s:map-of

function: (s:map-of key-type value-type)

Returns a constraint for sorted-maps that checks every key matches key-type and every value matches value-type, for a map keyed by data such as prices by SKU. Example: (s:map-of s:string s:number).

s:may-have-key

function: (s:may-have-key key &rest allowed-types)

Returns a constraint for sorted-maps that checks if the key exists, and if so, validates its value matches one of the allowed types. If the key is absent, validation passes. key is a string, matching has-key. Returns the key name on success (used by no-other-keys).

s:method

macro: (s:method name formals &rest body)

Declares a method inside s:make-record: (s:method name (recv args...) body...). The first formal, recv, is the object the method is called on; the call (obj 'name args...) passes only args. A formal after recv may be [name type]: each argument the call gives for it is checked before the body runs. The type :self is the type being defined, and [name 'T] resolves T on each call. Outside s:make-record it is an error.

s:negative

function: (s:negative)

Returns a constraint that checks if the input is strictly less than zero. NaN is neither positive nor negative.

s:nil

variable

Type name for (), so (s:may-have-key "k" s:string s:nil) allows a nil value.

s:no-other-keys

function: (s:no-other-keys &rest constraints)

Returns a constraint for sorted-maps that rejects maps with keys not declared by the given has-key or may-have-key constraints. Pass all key constraints as arguments.

s:not

function: (s:not constraint)

Returns a constraint that negates another constraint. The input passes if the inner constraint fails, and fails if the inner constraint passes.

s:number

variable

Type name for numeric values (int or float).

s:of

function: (s:of &rest allowed-types)

Returns a constraint for arrays and lists that checks each element matches one of the allowed types. Each allowed-type is a type string passed to the type handler. Example: (s:of "string") checks all elements are strings.

s:positive

function: (s:positive)

Returns a constraint that checks if the input is strictly greater than zero. NaN is neither positive nor negative.

s:record?

function: (s:record? value)

Returns true if value is a record object.

s:ref

function: (s:ref type)

Returns a type that passes an object of the record type and checks nothing else: no field check and no :check, so it is cheap. The type itself, used as a type, checks every field. s:ref does not prove the fields are valid: a getter returns a field's own value, and code that changes it in place (assoc!) is not checked. Use it for objects your own code made.

s:regexp

function: (s:regexp pattern)

Returns a constraint that checks if a string input matches the given regular expression pattern. Uses Go RE2 syntax. Returns an error if the pattern is invalid.

s:sequence

variable

Type name for a list or a vector. The s:len constraints measure a vector, not a list.

s:set-field!

function: (s:set-field! obj field value)

Sets a field of a record object, (s:set-field! obj 'field value), and returns the value. The field's validator checks the value first; a failure leaves the object as it was. It raises record-error unless a method of the object's type runs on the object, and while the object's :check runs: code outside the type changes an object through its methods.

s:sorted-map

variable

Type name for sorted-map (associative array) values.

s:string

variable

Type name for string values.

s:tagged-value

variable

Type name for user-defined tagged values (created with deftype/new).

s:validate

function: (s:validate type input)

Validates input against a type validator function (created by make-validator). Returns nil on success or an error with a condition string describing the validation failure.

s:when

function: (s:when key constraint matchKey &rest constraints)

Returns a conditional constraint for sorted-maps. When the value at key satisfies constraint, the value at matchKey must satisfy all additional constraints. If the condition is not met, the constraint passes.

string

String manipulation: case conversion, splitting, joining, repetition, trimming, and prefix, suffix and substring tests.

string:contains?

function: (string:contains? str substr)

Returns true if substr occurs anywhere in str. An empty substr is contained in every string. Comparison is by bytes; when both strings are valid UTF-8 this equals comparing runes. No Unicode normalization is applied.

string:has-prefix?

function: (string:has-prefix? str prefix)

Returns true if str begins with prefix. An empty prefix matches every string. Comparison is by bytes; when both strings are valid UTF-8 this equals comparing runes. No Unicode normalization is applied.

string:has-suffix?

function: (string:has-suffix? str suffix)

Returns true if str ends with suffix. An empty suffix matches every string. Comparison is by bytes; when both strings are valid UTF-8 this equals comparing runes. No Unicode normalization is applied.

string:join

function: (string:join list sep)

Concatenates a list of strings with sep inserted between each element. All items must be strings; output must fit the byte limit.

string:lowercase

function: (string:lowercase str)

Returns str in Unicode lowercase, reusing storage if unchanged.

string:repeat

function: (string:repeat str n)

Repeats str n times (n must be non-negative). Zero yields an empty string; one reuses str. Other results must fit the byte limit.

string:split

function: (string:split str sep)

Splits str around sep into a list of substrings. An empty sep splits by UTF-8 rune; empty str then yields no pieces. Takes exactly two arguments, str and sep. The runtime allocation limit counts pieces.

string:trim

function: (string:trim str cutset)

Returns str with all leading and trailing characters found in cutset removed. The cutset is a string of individual characters to trim, not a prefix/suffix.

string:trim-left

function: (string:trim-left str cutset)

Returns str with all leading characters found in cutset removed. The cutset is a string of individual characters to trim.

string:trim-prefix

function: (string:trim-prefix str prefix)

Returns str with one leading occurrence of prefix removed. If str does not begin with prefix, str is returned unchanged. Unlike trim-left, prefix is matched as a whole string, not as a set of characters.

string:trim-right

function: (string:trim-right str cutset)

Returns str with all trailing characters found in cutset removed. The cutset is a string of individual characters to trim.

string:trim-space

function: (string:trim-space str)

Returns str with all leading and trailing whitespace removed (spaces, tabs, newlines, etc.).

string:trim-suffix

function: (string:trim-suffix str suffix)

Returns str with one trailing occurrence of suffix removed. If str does not end with suffix, str is returned unchanged. Unlike trim-right, suffix is matched as a whole string, not as a set of characters.

string:uppercase

function: (string:uppercase str)

Returns str in Unicode uppercase, reusing storage if unchanged.

testing

Test framework: define named tests and benchmarks with assertion helpers (assert-equal, assert-nil, assert-not-nil, etc.).

testing:assert-equal

macro: (testing:assert-equal expect expression)

Asserts that two expressions are structurally equal using equal?. Works with any value types. Reports the expected and actual values on failure.

testing:assert-nil

macro: (testing:assert-nil expression)

Asserts that expression evaluates to nil. Reports the actual value on failure.

testing:assert-not

macro: (testing:assert-not expression)

Asserts that expression evaluates to a falsey value (nil or false). Reports the actual value on failure.

testing:assert-not-nil

macro: (testing:assert-not-nil expression)

Asserts that expression does not evaluate to nil. Reports the expression on failure.

testing:assert-string=

macro: (testing:assert-string= expect str)

Asserts that two expressions evaluate to equal strings. Both expect and str must evaluate to string values. Reports the expected and actual values on failure.

testing:assert=

macro: (testing:assert= expect num)

Asserts that two expressions evaluate to numerically equal values. Both expect and num must evaluate to numbers (int or float). Reports the expected and actual values on failure.

testing:benchmark

operator: (testing:benchmark name args &rest exprs)

Defines a named benchmark. name must be a string. args is a list containing a single symbol that receives the iteration count. The body should use dotimes or similar to run the benchmarked code count times. Prefer benchmark-simple for simple cases. Like test, benchmark is only available while running tests.

testing:benchmark-simple

macro: (testing:benchmark-simple name &rest exprs)

Defines a simple benchmark that runs exprs repeatedly. Expands to (benchmark name (count) (dotimes (_ count) exprs...)). The iteration count is provided by the benchmark harness.

testing:test

operator: (testing:test name &rest exprs)

Defines a named test case. name must be a string. The body expressions are wrapped in a lambda, written in the current package like a defun body, and registered with the test suite for later execution. Use the testing package's assert macros inside the body to check conditions. Tests can only be defined while running tests: outside a test runner there is no test suite and test signals an error.

testing:test-let

macro: (testing:test-let name bindings &rest exprs)

Defines a named test with local let bindings. Expands to (test name (let (bindings) exprs...)). The bindings use parallel binding (let) semantics.

testing:test-let*

macro: (testing:test-let* name bindings &rest exprs)

Defines a named test with local let* bindings. Like test-let but uses sequential binding (let*) semantics, so later bindings can reference earlier ones.

time

Time operations: parsing, formatting, comparison, and arithmetic on UTC timestamps and durations. Wraps Go's time package.

time:duration-ms

function: (time:duration-ms time-duration)

Returns the number of milliseconds in the duration as a float. The argument must be a native duration value.

time:duration-ns

function: (time:duration-ns time-duration)

Returns the number of nanoseconds in the duration as an integer. The argument must be a native duration value. Returns an error if the value overflows an int.

time:duration-s

function: (time:duration-s time-duration)

Returns the number of seconds in the duration as a float. The argument must be a native duration value.

time:format-rfc3339

function: (time:format-rfc3339 datetime)

Formats a native time value as an RFC 3339 string with second precision (e.g. "2023-01-15T10:30:00Z"). Returns a string. The argument must be a native time value from parse-rfc3339 or a host-supplied timestamp.

time:format-rfc3339-nano

function: (time:format-rfc3339-nano datetime)

Formats a native time value as an RFC 3339 string with nanosecond precision (e.g. "2023-01-15T10:30:00.123456789Z"). Returns a string. The argument must be a native time value.

time:parse-duration

function: (time:parse-duration duration-string)

Parses a Go-style duration string and returns a native duration value. Valid units are "ns", "us" (or "µs"), "ms", "s", "m", "h". Examples: "1h30m", "500ms", "2h45m30s". Returns an error if the string cannot be parsed.

time:parse-rfc3339

function: (time:parse-rfc3339 timestamp)

Parses an RFC 3339 timestamp string (e.g. "2023-01-15T10:30:00Z") and returns a native time value. Returns an error if the string is not valid RFC 3339 format. For nanosecond precision, use parse-rfc3339-nano.

time:parse-rfc3339-nano

function: (time:parse-rfc3339-nano timestamp)

Parses an RFC 3339 timestamp string with nanosecond precision (e.g. "2023-01-15T10:30:00.123456789Z") and returns a native time value. Returns an error if the string is not valid format.

time:time-add

function: (time:time-add datetime duration)

Returns a new time value equal to datetime plus duration. The first argument must be a native time value and the second must be a native duration value (from parse-duration or time-from).

time:time-from

function: (time:time-from start end)

Returns the duration between start and end as a native duration value (end - start). Both arguments must be native time values. The result can be negative if end is before start.

time:time<

function: (time:time< a b)

Returns true if time a is before time b. Both arguments must be native time values.

time:time=

function: (time:time= a b)

Returns true if the two native time values represent the same instant. Both arguments must be native time values.

time:time>

function: (time:time> a b)

Returns true if time a is after time b. Both arguments must be native time values.

We use cookies to give you the best experience of using this website. By continuing to use this site, you accept our use of cookies. Please read our Cookie Policy for more information.