By Christian Findlay

Built-in Functions

Reference for built-in functions available in every Osprey program. Fallible language operations use Result or a statically handled effect. Raw foreign status values must be translated at a safe Osprey boundary. See Error Handling.

Built-ins are shared by both language flavors. Examples use the Default surface unless an ML example clarifies different call syntax.

Basic I/O Functions

print(value: printable) -> Unit — [BUILTIN-PRINT]

printable is documentation shorthand, not a user-declared type. It includes int, float, bool, string, Unit, explicitly erased any, and Result<T, E> when both payloads are printable. Concrete records, collections, functions, iterators, fibers, channels, and pointers are rejected. Results render as Success(value) or Error(message); Unit renders as 0; print appends a newline. An explicitly erased any value is a compatibility exception, not a dynamic formatter: if it hides an aggregate, the raw pointer-sized value is rendered rather than the aggregate's contents.

print("Hello World")
print(42)
print(true)
print "Hello World"
print 42
print true

input() -> string — [BUILTIN-INPUT]

Reads one line from standard input (without its trailing newline) and returns it as a string. End-of-file ends a line just as a newline does, and at end-of-file with nothing read — including when stdin is closed or not connected — the result is the empty string "" rather than a failure. Elapsed silence is not end-of-file: a producer that is connected but has not written yet is waited for, so a slow writer's line still arrives whole. A launcher that cannot supply input must close the child's standard input. Parse the line with parseInt/parseFloat when a number is wanted.

let line = input()                 // "" if there is no input
let n    = parseInt(input()) ?: 0  // a number, or 0 when absent/unparseable
line = input ()                    // "" if there is no input
n =
    match parseInt (input ())      // a number, or 0 when absent/unparseable
        Success value => value
        Error _       => 0

toString(value: printable) -> string — [BUILTIN-TOSTRING]

Uses the same accepted types and formatting as print, without writing output.

Testing Functions

test(name: string, body: fn() -> a) -> Unit
expect(actual: any, expected: any) -> Unit
check(label: string, expected: any, actual: any) -> Unit

Their behavior, shadowing rule, TAP output, filtering, discovery, coverage, and editor integration are specified in Testing Framework.

Numeric Functions

The numeric builtins are inside the arithmetic totality guarantee: none may trap, panic, wrap silently, or return an unspecified value (ARITH-TOTAL). abs and intDiv follow the operators — plain int, with faults dispatched to the Arith handler. checkedAdd/checkedSub/checkedMul return a Result and are the explicit value-level form for code that wants overflow as data.

abs(n: int) -> int — [BUILTIN-ABS] Returns the absolute value. Because 2^63 is not representable, the minimum signed 64-bit input performs Arith.overflow; it never wraps or panics.

intDiv(a: int, b: int) -> int — [BUILTIN-INTDIV]

Truncates toward zero. A zero divisor performs Arith.remainderByZero; intDiv(-9223372036854775808, -1) performs Arith.overflow; every other input yields the quotient. The / operator instead returns float.

intDiv(7, 2)        // 3
intDiv(255643, 10)  // 25564
intDiv(5, 0)        // performs Arith.remainderByZero
intDiv(-9223372036854775808, -1) // performs Arith.overflow
fn half(n) = intDiv(n, 2)

toFloat(n: int) -> float — [BUILTIN-TOFLOAT]

Widens an integer to the nearest double, rounding ties to even. Exact for |n| <= 2^53; larger magnitudes round, which is the IEEE-754 result and not an error. The conversion is total — every int has a nearest double — so it returns a bare float, not a Result.

This is the explicit element conversion GPU kernels use; a buffer never widens implicitly at its boundary (GPU-CONVERT). It may be passed by name as a kernel, not only called directly.

toFloat(7)                        // 7.0
toFloat(-3)                       // -3.0
gpuIota(1000) |> gpuMap(toFloat)  // GpuBuffer<float>, 0.0 .. 999.0
intDiv (7, 2)        // Success(3)
intDiv (255643, 10)  // Success(25564)
intDiv (5, 0)        // Error — "division by zero"
intDiv (-9223372036854775808, -1) // Error — "integer overflow"

half : int -> Result<int, Error>
half n = intDiv (n, 2)

half infers int and requires an Arith handler at the program entry.

checkedAdd / checkedSub / checkedMul — [BUILTIN-CHECKED-ARITH]

Each has signature (a: int, b: int) -> Result<int, Error>. Overflow-checked integer addition, subtraction, and multiplication, lowering to llvm.sadd.with.overflow, llvm.ssub.with.overflow, and llvm.smul.with.overflow respectively. An overflowing operation returns Error; otherwise Success(result). They are the value-level form of overflow checking, for code that wants the failure as data rather than as an Arith operation (ARITH-CHECKED). Their Success payload is never implicitly unwrapped.

checkedAdd(2, 3)                      // Success(5)
checkedMul(4294967296, 4294967296)    // Error — "integer overflow"
fn twice(n) -> Result<int, Error> = checkedMul(n, 2)
checkedAdd (2, 3)                      // Success(5)
checkedMul (4294967296, 4294967296)    // Error — "integer overflow"

twice : int -> Result<int, Error>
twice n = checkedMul (n, 2)

random() -> int — [BUILTIN-RANDOM]

A cryptographically-secure uniform random non-negative integer in [0, 2^63-1], drawn fresh from the operating system's CSPRNG (arc4random_buf on macOS/BSD, getrandom(2) on Linux, falling back to /dev/urandom, rand_s on Windows, getentropy on wasm). It carries no userspace seed or state, so calls are not reproducible.

A draw either carries OS entropy or the process stops. random() answers int, not Result<int, Error>, so a source that cannot supply the bytes has nowhere to report — and a predictable value returned from this call is undetectable by the caller and worst exactly where it matters, since the WebSocket handshake nonce draws from it too. When no source can fill the request the runtime prints FATAL: the OS entropy source gave <n> of the <m> bytes random() needs and aborts; it never substitutes zeros or leaves the caller's word unwritten. On the supported platforms no source fails, so this is unreachable in practice and is reached in the test suite only by taking the source away.

let token = random()        // e.g. 7240982340198 (varies every call)
fn coinFlip() = randomBelow(2) ?: 0   // 0 or 1
token = random ()        // e.g. 7240982340198 (varies every call)
coinFlip () =
    match randomBelow 2   // 0 or 1
        Success value => value
        Error _       => 0

randomBelow(n: int) -> Result<int, Error> — [BUILTIN-RANDOM-BELOW]

A cryptographically-secure uniform random integer in the half-open range [0, n). The result is unbiased: it is drawn by rejection sampling, so every value in the range is equally likely (a plain random() % n is not). A non-positive n returns Error; otherwise Success(value) with 0 <= value < n. Compose for an arbitrary range: lo + (randomBelowhi - lo).

let die = randomBelow(6) ?: 0          // a fair face 0..5
match randomBelow(0) { Success { value } => value  Error { message } => 0 - 1 }  // Error
die =
    match randomBelow 6           // a fair face 0..5
        Success value => value
        Error _       => 0
match randomBelow 0
    Success value => value
    Error message => 0 - 1       // Error

String Functions

Strings are immutable, NUL-terminated UTF-8 byte sequences. String operations return new values and do not mutate their arguments.

Rules

Total operations return plain values; invalid indices, arguments, or parses return Result. The subject is the first argument so calls compose with |>. Except for the explicit UTF-8 cursor functions, lengths and indices are byte based. Case conversion and whitespace handling cover ASCII.

Calling Style — [BUILTIN-STRING-UFCS]

String functions support pipe, direct-call, and Default-flavor method syntax.

// Pipe chain
"  Hello, World  " |> trim |> toLowerCase |> split(", ")

// Direct call
toLowerCase(trim("  Hello  "))

// Method-call (UFCS) — sugar, equivalent to the direct form
"  Hello  ".trim().toLowerCase()
// Pipe chain
"  Hello, World  " |> trim |> toLowerCase |> split ", "

// Direct call
toLowerCase (trim "  Hello  ")

// Chained UFCS (`.trim().toLowerCase()`) has no ML surface; use the pipe form:
"  Hello  " |> trim |> toLowerCase

All three desugar to the same call. Rules:

  • Pipe (x |> f) rewrites to f(x). With extra args, x |> f(a, b) becomes f(x, a, b). A bare identifier on the right (x |> f) is auto-promoted to a call — no parens needed for single-arg functions. See Iterators.
  • UFCS (x.f(args)) rewrites to f(x, args). Parens are required to disambiguate from field access — x.f always means field access, never a method call. If a record has a field named f, field access wins; UFCS is the fallback.
  • Direct call is ordinary function application.

Multi-argument functions in this spec are documented subject-first (e.g. split(s: string, separator: string)) so all three forms work uniformly.

Inspection (total) — [BUILTIN-STRING-INSPECTION]

length(s: string) -> int — [BUILTIN-STRING-LENGTH]

Returns the number of bytes. It is equivalent to byteLength for strings.

isEmpty(s: string) -> bool — [BUILTIN-STRING-ISEMPTY]

True iff length(s) == 0. Equivalent to length(s) == 0 but constant-time. The same names accept List<T> and Map<string, V> as described under Collection Functions; no other receiver type is accepted.

contains(s: string, needle: string) -> bool — [BUILTIN-STRING-CONTAINS]

True if needle occurs anywhere in s. An empty needle returns true.

contains("hello world", "world")  // true
contains("hello", "")             // true
contains ("hello world", "world")  // true
contains ("hello", "")             // true

startsWith(s: string, prefix: string) -> bool — [BUILTIN-STRING-STARTSWITH]

endsWith(s: string, suffix: string) -> bool — [BUILTIN-STRING-ENDSWITH]

"GET /api/users" |> startsWith("GET ")   // true
"image.png"      |> endsWith(".png")     // true
"GET /api/users" |> startsWith "GET "   // true
"image.png"      |> endsWith ".png"     // true

indexOf(s: string, needle: string) -> Result<int, Error> — [BUILTIN-STRING-INDEXOF]

Returns the byte index of the first occurrence of needle, or Error with "indexOf: substring not found" if absent. An empty needle returns Success { value: 0 }.

Cursor Access — [BUILTIN-STRING-CURSOR]

These primitives give indexed access to UTF-8 bytes and codepoints. Only byteLength is total; byteAt, codePointAt, and codePointWidth are fallible and return Result on a bad index, a non-boundary index, or malformed UTF-8. Only fromCodePoint allocates.

A runtime string is a bare NUL-terminated char* carrying no stored length, so every entry point here begins with a strlen and is O(n) in the string's byte length, not O(1). A scan that re-derives byteLength per step is therefore quadratic. Making these O(1) requires a length-carrying string ABI.

byteLength(s: string) -> int — [BUILTIN-STRING-BYTELENGTH]

Byte length of the underlying UTF-8 storage. Equivalent to length(s).

byteAt(s: string, i: int) -> Result<int, Error> — [BUILTIN-STRING-BYTEAT]

Returns the UTF-8 byte at index i as an int in [0, 255], or Error if i < 0 or i >= byteLength(s). Does not allocate.

codePointAt(s: string, byteIndex: int) -> Result<int, Error> — [BUILTIN-STRING-CODEPOINTAT]

Decodes the UTF-8 codepoint starting at byteIndex and returns it as an int. Returns Error if the index is out of range, does not land on a codepoint boundary, or begins a truncated, overlong, surrogate, out-of-range, or otherwise malformed UTF-8 sequence. Decoding reads at most 4 bytes once the index is bounds-checked. Pair with codePointWidth to advance:

type CharStep = { codePoint: int, nextIndex: int }

fn nextChar(s, i) = match codePointAt(s, i) {
    Success { value: cp } => match codePointWidth(cp) {
        Success { value: w } => Success { value: CharStep { codePoint: cp, nextIndex: i + w } }
        Error   { message }  => Error { message }
    }
    Error { message } => Error { message }
}
type CharStep =
    codePoint : int
    nextIndex : int

nextChar (s, i) =
    match codePointAt (s, i)
        Success cp =>
            match codePointWidth cp
                Success w => Success(value = CharStep(codePoint = cp, nextIndex = i + w))
                Error message => Error(message = message)
        Error message => Error(message = message)

codePointWidth(codepoint: int) -> Result<int, Error> — [BUILTIN-STRING-CODEPOINTWIDTH]

Returns the number of UTF-8 bytes the codepoint encodes to (1–4), or Error if codepoint is not a valid Unicode scalar value.

fromCodePoint(codepoint: int) -> Result<string, Error> — [BUILTIN-STRING-FROMCODEPOINT]

Builds a single-codepoint string. Inverse of codePointAt. Returns Error for surrogates, values outside 0..0x10FFFF, and U+0000, which the NUL-terminated string ABI cannot represent.

Substrings — [BUILTIN-STRING-SUBSTRINGS]

substring(s: string, start: int, end: int) -> Result<string, Error> — [BUILTIN-STRING-SUBSTRING]

Extracts bytes in [start, end). Returns Error if start < 0, end > length(s), or start > end.

take(s: string, n: int) -> string — [BUILTIN-STRING-TAKE]

Returns at most the first n bytes. If n <= 0, returns ""; if n >= length(s), returns s.

drop(s: string, n: int) -> string — [BUILTIN-STRING-DROP]

Returns s without its first n bytes, with the same clamping rules as take.

Splitting and Joining — [BUILTIN-STRING-LIST]

split(s: string, separator: string) -> Result<List<string>, Error> — [BUILTIN-STRING-SPLIT]

Splits s on every occurrence of separator. Returns Error with "split: separator must not be empty" if separator is empty.

match split("a,b,c", ",") {
    Success { value }   => forEachList(value, print)   // "a" "b" "c"
    Error   { message } => print("split error")
}
match split ("a,b,c", ",")
    Success value   => forEachList (value, print)   // "a" "b" "c"
    Error message   => print "split error"

join(parts: List<string>, separator: string) -> string — [BUILTIN-STRING-JOIN]

Concatenates parts with separator between each pair. Returns "" if parts is empty.

lines(s: string) -> List<string> — [BUILTIN-STRING-LINES]

Splits on "\n". A trailing newline does not produce an empty final element.

words(s: string) -> List<string> — [BUILTIN-STRING-WORDS]

Splits on runs of ASCII whitespace, dropping empty results.

Transformation (total) — [BUILTIN-STRING-TRANSFORM]

toUpperCase(s: string) -> string — [BUILTIN-STRING-TOUPPERCASE]

toLowerCase(s: string) -> string — [BUILTIN-STRING-TOLOWERCASE]

ASCII case conversion. Other bytes are copied unchanged.

trim(s: string) -> string — [BUILTIN-STRING-TRIM]

trimStart(s: string) -> string — [BUILTIN-STRING-TRIMSTART]

trimEnd(s: string) -> string — [BUILTIN-STRING-TRIMEND]

Remove leading, trailing, or both runs of ASCII whitespace.

replace(s: string, needle: string, replacement: string) -> Result<string, Error> — [BUILTIN-STRING-REPLACE]

Replaces every occurrence of needle with replacement. Returns Error if needle is empty.

repeat(s: string, n: int) -> Result<string, Error> — [BUILTIN-STRING-REPEAT]

Concatenates s with itself n times. Returns Error if n < 0. repeat(s, 0) == "".

reverse(s: string) -> string — [BUILTIN-STRING-REVERSE]

Reverses byte order.

padStart(s: string, targetLength: int, fill: string) -> Result<string, Error> — [BUILTIN-STRING-PADSTART]

padEnd(s: string, targetLength: int, fill: string) -> Result<string, Error> — [BUILTIN-STRING-PADEND]

Pads s on the left or right with repeated bytes from fill until it reaches targetLength bytes. Returns s unchanged if already long enough and Error if fill is empty.

Parsing — [BUILTIN-STRING-PARSING]

parseInt(s: string) -> Result<int, Error> — [BUILTIN-STRING-PARSEINT]

Parses a base-10 signed integer. Leading/trailing whitespace is rejected; callers must trim first. Returns Error on invalid or out-of-range input.

parseFloat(s: string) -> Result<float, Error> — [BUILTIN-STRING-PARSEFLOAT]

Parses a finite base-10 number with an optional sign, decimal point, and decimal exponent. At least one digit is required; surrounding whitespace, NaN, infinity, hexadecimal floats, malformed exponents, and non-finite results return Error.

Concatenation Operator — [BUILTIN-STRING-CONCAT]

The + operator on two string values returns string directly. String concatenation cannot fail and is never Result-wrapped.

let greeting = "Hello, " + name + "!"
greeting = "Hello, " + name + "!"

File System Functions — [BUILTIN-FILE]

writeFile(path: string, content: string) -> Result<int, Error>

Writes or replaces a file and returns the number of bytes written. Success means every byte reached the file: a partial write and a failed flush are both Error. Buffering means the bytes leave for the file when it is closed, so a full disk or a hung-up pipe is discovered there rather than at the write, and either one is reported.

readFile(path: string) -> Result<string, Error>

Reads a complete stream. The length is whatever the stream produced, not what seeking to the end claimed it would be — a FIFO, socket or character device cannot be seeked and reports its size as -1, so a seek-derived length reads those sources as empty and truncates or overruns their contents.

Failure reasons — [BUILTIN-FILE-ERRMSG]

An Error from a file operation carries the operation, the subject and the operating system's own explanation:

match writeFile("out/report.txt", body) {
    Success { value } => print("wrote ${toString(value)} bytes")
    Error { message } => print(message)  // writeFile: out/report.txt: No such file or directory
}

Discarding that reason makes a missing directory, a permissions denial and a full disk indistinguishable at the point they are handled, so a program cannot choose to create the directory, ask for access, or free space. The reason travels on a thread-local channel that the caller clears immediately before the operation and takes ownership of immediately after, which is what lets a Result outlive later I/O without inheriting an unrelated failure's message. A runtime operation that reports no reason falls back to a fixed description.

Process Operations — [BUILTIN-PROCESS]

spawnProcess(command: string, callback: fn(int, int, string) -> Unit) -> Result<int, Error>

Starts a process and returns its handle. The callback receives the handle, event kind (1 stdout, 2 stderr, 3 exit), and event text.

fn processEventHandler(processID, eventType, data) = match eventType {
    1 => print("[STDOUT] ${data}")
    2 => print("[STDERR] ${data}")
    3 => print("[EXIT] Code: ${data}")
    _ => print("[UNKNOWN] ${data}")
}

let result = spawnProcess("echo 'Hello'", processEventHandler)

awaitProcess(processId: int) -> int

Waits for process completion and returns the exit code, or -1 if the handle is outside the valid range or has no process.

cleanupProcess(processId: int) -> Unit

Releases process resources.

Failure and resource release — [BUILTIN-PROCESS-FAILURE]

spawnProcess yields Success only for a handle a monitor is already watching; every other outcome is Error. The runtime distinguishes them as -1 a missing command or callback, -2 the handle space is used up, -3 the process record could not be allocated, -4 a pipe could not be opened, -5 the monitor thread could not be started, and -6 the process could not be created. The argument check runs before the capacity check, so a call that is both malformed and unaffordable reports -1.

Every failing path leaves the process as the call found it: no descriptor opened for the attempt stays open, no child stays unreaped, no table slot stays occupied, and a later spawnProcess succeeds once the condition clears. A failed spawn does consume a handle number — handle numbers only ever increase — but never a table slot. awaitProcess on a handle whose slot was released returns -1.

JSON Document Functions — [BUILTIN-JSON]

jsonParse(text: string) -> Result<int, Error>
jsonGet(document: int, path: string) -> Result<string, Error>
jsonLength(document: int, path: string) -> int
jsonFree(document: int) -> Result<int, Error>

jsonParse returns a positive opaque document handle. Paths use dotted object keys and bracketed array indices, such as user.items[0].name; "" addresses the root. jsonGet converts a string, number, boolean, or null scalar to a string and returns Error for an invalid path, handle, array, or object. jsonLength returns an array length or object member count and returns -1 for an invalid path, handle, or scalar. A successful handle must be released once with jsonFree; an invalid handle or double free returns Error.

Malformed documents and string grammar — [BUILTIN-JSON-STRING]

jsonParse returns Error for any text that is not one complete JSON value, and it returns exactly that one failure: a document is either parsed whole or rejected whole, never truncated at the first surprise and reported as a success. Trailing text after the value, a missing separator, an unterminated container, and an empty document are all rejections.

Inside a string the accepted grammar is RFC 8259's, with no extensions:

  • the only escapes are \", \\, \/, \b, \f, \n, \r, \t and \uXXXX. Any other character after a backslash is a rejection — the backslash is never dropped and the character never taken literally;
  • \u must be followed by exactly four hexadecimal digits. Fewer digits, a non-hexadecimal digit, or the end of the text is a rejection;
  • a \u escape naming a high surrogate (U+D800–U+DBFF) must be immediately followed by a \u escape naming a low surrogate (U+DC00–U+DFFF); the pair decodes to the one code point they spell. A high surrogate followed by anything else, and a low surrogate that no high surrogate precedes, are both rejections; and
  • the characters U+0000 through U+001F must appear escaped. A raw one is a rejection; and
  • the text is UTF-8. A literal byte sequence that is not valid UTF-8 — an overlong form, a surrogate spelled in UTF-8, a code point past U+10FFFF, a truncated sequence, or a continuation byte with no lead — is a rejection, exactly as the equivalent \u escape is; and
  • \u0000 is rejected outright, escaped or not. Every scalar is delivered as a NUL-terminated string, so a decoded U+0000 would not embed a NUL — it would truncate the value, and "a\u0000b" would read back as a with nothing reporting the loss.

Number grammar — [BUILTIN-JSON-NUMBER]

A number is stored as its source text and jsonGet returns that text unchanged, so whatever the grammar accepts is what a caller reads back. The accepted form is RFC 8259's, and nothing else:

number = [ "-" ] int [ frac ] [ exp ]
int    = "0" / ( digit1-9 *DIGIT )
frac   = "." 1*DIGIT
exp    = ( "e" / "E" ) [ "+" / "-" ] 1*DIGIT

So -, +1, .5, 1., 1.e5, 1e, 1e+, --1 and 1..2 are all rejected, and a leading zero ends the integer part: 01 is 0 followed by text that is not part of the number. Inside a container that unfinished number makes the whole document malformed; at the root a value that is complete and followed by more text is the distinct trailing-text failure instead.

Allocation failure at any point during a parse is reported the same way as malformed input — Error, no handle, and nothing retained — because a partially built document is not a document. A parse that fails, for either reason, frees everything it allocated.

Terminal Functions — [BUILTIN-TERM]

termReadKey() -> Result<string, Error>
termRawMode(enabled: int) -> Unit
termCols() -> int
termRows() -> int
termClear() -> int
termMoveCursor(row: int, column: int) -> int
termHideCursor() -> int
termShowCursor() -> int

On POSIX terminals, termRawMode(1) disables canonical input and echo and enters the alternate screen; termRawMode(0) restores the saved mode and screen. Its native status is not exposed. termReadKey returns normalized key names such as Enter, Up, or Ctrl-C, or the literal input byte. termCols and termRows return -1 when the terminal size is unavailable. The remaining functions write ANSI control sequences and return 0; cursor coordinates below 1 are clamped to 1. Windows implementations return Error from termReadKey, do nothing for raw mode, and return -1 from the integer functions.

Collection Functions

Collection operations return new values without changing their inputs. Except for length and isEmpty, public names are prefixed with list or map.

Common (List and Map)

length(list: List<T>) -> int   /   length(map: Map<string, V>) -> int — [BUILTIN-COLLECTION-LENGTH]

Returns the element count. listLength and mapLength are equivalent type-specific spellings.

isEmpty(list: List<T>) -> bool   /   isEmpty(map: Map<string, V>) -> bool — [BUILTIN-COLLECTION-ISEMPTY]

Returns whether the element count is zero. The receiver type selects string, list, or map behavior for both common functions.

List<T> — [BUILTIN-LIST]

List() creates an empty list. List literals create populated lists.

listGet(list: List<T>, index: int) -> Result<T, Error> — [BUILTIN-LIST-GET]

Equivalent to list[index]. An out-of-range index returns Error.

listPrepend(list: List<T>, value: T) -> List<T> — [BUILTIN-LIST-PREPEND]

Returns a list with value at the front.

listAppend(list: List<T>, value: T) -> List<T> — [BUILTIN-LIST-APPEND]

Returns a list with value at the end.

listConcat(left: List<T>, right: List<T>) -> List<T> — [BUILTIN-LIST-CONCAT]

Concatenates two lists. left + right is equivalent.

listReverse(list: List<T>) -> List<T> — [BUILTIN-LIST-REVERSE]

Returns the elements in reverse order.

listContains(list: List<T>, value: T) -> bool — [BUILTIN-LIST-CONTAINS]

Strings compare by content. Scalar values compare by value; managed handles such as nested lists and records compare by identity.

forEachList(list: List<T>, function: fn(T) -> Unit) -> Unit — [BUILTIN-LIST-FOREACH]

Calls function once per element in index order.

Map<string, V> — [BUILTIN-MAP]

Map() and map literals create string-keyed maps. Map iteration order is unspecified.

mapGet(map: Map<string, V>, key: string) -> Result<V, Error> — [BUILTIN-MAP-GET]

Equivalent to map[key]. A missing key returns Error.

mapContains(map: Map<string, V>, key: string) -> bool — [BUILTIN-MAP-CONTAINS]

Returns whether key is present.

mapSet(map: Map<string, V>, key: string, value: V) -> Map<string, V> — [BUILTIN-MAP-SET]

Returns a map with key bound to value, replacing any prior binding.

mapRemove(map: Map<string, V>, key: string) -> Map<string, V> — [BUILTIN-MAP-REMOVE]

Returns a map without key. A missing key leaves the map unchanged.

mapMerge(left: Map<string, V>, right: Map<string, V>) -> Map<string, V> — [BUILTIN-MAP-MERGE]

Returns the right-biased union. left + right is equivalent.

mapKeys(map: Map<string, V>) -> List<string> — [BUILTIN-MAP-KEYS]

Returns all keys in unspecified order.

mapValues(map: Map<string, V>) -> List<V> — [BUILTIN-MAP-VALUES]

Returns all values in the same traversal order as mapKeys.

Iterators and Pipe

range, forEach, map, filter, fold, and |> are documented in Iterators and Iteration.

HTTP

See HTTP.

WebSockets

See WebSockets.

Fibers and Channels

spawn, await, send, recv, yield, Fiber<T>, Channel<T> are documented in Fibers and Concurrency.

GPU Computation

toGpu, fromGpu, gpuLength, gpuMap, gpuFold, and GpuBuffer<T> are documented in GPU Computation.