/ Documentation
Playground Libraries Home GitHub
382 functions across 36 categories

String Interpolation

"hello ${name}"

Embed any expression inside a string with ${...}. The expression is evaluated and converted to a string at runtime.

let name = "world"
print("hello ${name}")              // hello world
print("2 + 2 = ${2 + 2}")            // 2 + 2 = 4
print("${name.to_upper()}")          // WORLD
print("len: ${[1,2,3].len()}")       // len: 3
print("escaped: \${literal}")        // escaped: ${literal}

Phase Constraints

fn name(param: flux Type)

Annotate function parameters with flux (or ~) to require a fluid argument, or fix (or *) to require a crystal argument. Passing an argument with an incompatible phase produces a runtime error. Parameters without a phase annotation accept any phase.

fn mutate(data: flux Map) { data.set("k", "v") }
fn inspect(data: fix Map) { print(data.get("k")) }

flux m = Map::new()
mutate(m)                            // ok — fluid matches flux

fix frozen = freeze(m)
inspect(frozen)                       // ok — crystal matches fix
mutate(frozen)                        // error — crystal rejected by flux
fn name(param: ~Type)  fn name(param: *Type)

The sigils ~ and * are shorthand for flux and fix in type annotations.

fn update(data: ~Map) { data.set("x", 1) }   // same as flux Map
fn read(data: *Map) { print(data) }            // same as fix Map

Phase-Dependent Dispatch

fn name(p: flux T)  +  fn name(p: fix T)

Define multiple functions with the same name but different phase annotations. The runtime dispatches to the best-matching overload based on the phases of the arguments at call time.

fn process(data: ~Map) { print("mutable path") }
fn process(data: *Map) { print("immutable path") }

flux m = Map::new()
process(m)                           // "mutable path"
freeze(m)
process(m)                           // "immutable path"
fn name(p: T) — fallback overload

An overload with no phase annotation acts as a fallback. It is selected when the argument has no specific phase or when no phase-annotated overload matches.

fn handle(data: ~Map) { print("flux") }
fn handle(data: Map)  { print("fallback") }

let m = Map::new()
handle(m)                            // "fallback" (unphased arg)

Core

input(prompt?: String) -> String

Read a line of input from stdin, optionally displaying a prompt.

input("Name: ")  // reads user input
typeof(val: Any) -> String

Returns the type name of a value as a string.

typeof(42)  // "Int"
phase_of(val: Any) -> String

Returns the phase of a value ("fluid", "crystal", "sublimated", or "unphased").

phase_of(freeze([1, 2]))  // "crystal"
to_string(val: Any) -> String

Convert any value to its string representation.

to_string(42)  // "42"
repr(val: Any) -> String

Return the repr string of a value. Strings are quoted, structs with a `repr` closure field use the custom representation.

repr(42)        // "42"
repr("hello")   // "\"hello\""
len(val: String|Array|Map) -> Int

Returns the length of a string, array, or map.

len("hello")  // 5
len([1, 2, 3])  // 3
exit(code?: Int) -> Unit

Exit the program with an optional exit code (default 0).

exit(1)  // exits with code 1
version() -> String

Return the Lattice interpreter version string.

version()  // "0.1.0"
print_raw(args: Any...) -> Unit

Print values separated by spaces without a trailing newline.

print_raw("hello", "world")  // prints: hello world
eprint(args: Any...) -> Unit

Print values to stderr with a trailing newline.

eprint("warning:", msg)  // prints to stderr
assert(cond: Any, msg?: String) -> Unit

Assert that a condition is truthy, or raise an error with an optional message.

assert(1 == 1, "math works")
debug_assert(cond: Any, msg?: String) -> Unit

Assert that a condition is truthy (no-op when assertions are disabled via --no-assertions).

debug_assert(x > 0, "x must be positive")
set_recursion_limit(n: Int) -> Unit

Set the maximum recursion depth for the tree-walk evaluator. Capped at 100000. Default is 1000.

set_recursion_limit(500)
recursion_limit() -> Int

Return the current maximum recursion depth.

recursion_limit()  // 1000
print(args: Any...) -> Unit

Print values separated by spaces with a trailing newline.

print("hello", "world")  // prints: hello world

Phase Transitions

grow(name: String) -> Any

Freeze a variable and validate any pending seed contracts.

grow(config)  // freeze + validate seeds
freeze(val: Any) -> Any

Transition a value to the crystal (immutable) phase. Frozen containers are stored once and shared by reference, so later copies, argument passes, and channel sends are O(1). Values containing closures, Refs, iterators, or channels — and scalars or short strings — keep plain copy semantics; behavior is identical either way.

freeze([1, 2, 3])  // crystal [1, 2, 3]
thaw(val: Any) -> Any

Transition a crystal value back to the flux (mutable) phase. Always produces a fresh mutable copy — other aliases of the frozen value are unaffected.

thaw(freeze([1, 2]))  // flux [1, 2]
clone(val: Any) -> Any

Create a deep copy of a value. The copy is guaranteed to be physically independent, even when the source is frozen data shared by reference — use it to detach a small piece of a large frozen structure.

clone(my_array)  // independent copy
anneal(val) |transform| { ... } -> Any

Atomically thaw a crystal value, apply a transformation, and refreeze.

anneal(frozen_map) |m| { m["key"] = "value"; m }

Type Constructors

Map::new() -> Map

Create a new empty map.

Map::new()  // {}
Channel::new() -> Channel

Create a new channel for concurrent communication.

Channel::new()  // <Channel>
Set::new() -> Set

Create a new empty set.

Set::new()  // Set{}
Set::from(array: Array) -> Set

Create a set from an array (duplicates removed).

Set::from([1, 2, 2, 3])  // Set{1, 2, 3}
Buffer::new(size: Int) -> Buffer

Create a new zero-filled buffer of the given size.

Buffer::new(16)  // Buffer<16 bytes>
Buffer::from(arr: Array) -> Buffer

Create a buffer from an array of byte integers (0-255).

Buffer::from([0xFF, 0x00, 0x42])
Buffer::from_string(s: String) -> Buffer

Create a buffer from a UTF-8 string.

Buffer::from_string("hello")
Ref::new(value: Any) -> Ref

Create a new reference-counted shared wrapper around a value.

Ref::new({})
range(start: Int, end: Int, step?: Int) -> Array

Generate an array of integers from start (inclusive) to end (exclusive).

range(0, 5)  // [0, 1, 2, 3, 4]
range(0, 10, 2)  // [0, 2, 4, 6, 8]

Type Conversion

ord(ch: String) -> Int

Return the Unicode code point of the first character.

ord("A")  // 65
chr(code: Int) -> String

Return the character for a Unicode code point.

chr(65)  // "A"
parse_int(s: String) -> Int

Parse a string as an integer.

parse_int("42")  // 42
parse_float(s: String) -> Float

Parse a string as a floating-point number.

parse_float("3.14")  // 3.14
to_int(val: Any) -> Int

Convert a value to an integer (truncates floats, parses strings).

to_int(3.9)  // 3
to_float(val: Any) -> Float

Convert a value to a floating-point number.

to_float(42)  // 42.0

Error Handling

error(msg: String) -> String

Create an error value with the given message.

error("something went wrong")  // "EVAL_ERROR:something went wrong"
panic(msg: String) -> Unit

Trigger an immediate fatal error that cannot be caught by try/catch.

panic("unrecoverable state")
is_error(val: Any) -> Bool

Check if a value is an error value.

is_error(error("oops"))  // true

Reflection

struct_name(val: Struct) -> String

Returns the type name of a struct instance.

struct_name(user)  // "User"
struct_fields(val: Struct) -> Array

Returns an array of field name strings from a struct instance.

struct_fields(user)  // ["name", "age"]
struct_to_map(val: Struct) -> Map

Converts a struct instance to a Map of {field_name: value}.

struct_to_map(user).get("name")  // "Alice"
struct_from_map(name: String, map: Map) -> Struct

Creates a struct instance from a type name and a Map of field values. Missing fields default to nil.

struct_from_map("User", m)

Math

abs(x: Int|Float) -> Int|Float

Return the absolute value of a number.

abs(-5)  // 5
floor(x: Int|Float) -> Int

Round down to the nearest integer.

floor(3.7)  // 3
ceil(x: Int|Float) -> Int

Round up to the nearest integer.

ceil(3.2)  // 4
round(x: Int|Float) -> Int

Round to the nearest integer.

round(3.5)  // 4
sqrt(x: Int|Float) -> Float

Return the square root of a number.

sqrt(16)  // 4.0
pow(base: Int|Float, exp: Int|Float) -> Float

Raise base to the power of exp.

pow(2, 10)  // 1024.0
min(a: Int|Float, b: Int|Float) -> Int|Float

Return the smaller of two numbers.

min(3, 7)  // 3
max(a: Int|Float, b: Int|Float) -> Int|Float

Return the larger of two numbers.

max(3, 7)  // 7
random() -> Float

Return a random float between 0.0 (inclusive) and 1.0 (exclusive).

random()  // 0.7231...
random_int(min: Int, max: Int) -> Int

Return a random integer in the range [min, max).

random_int(1, 100)  // 42
log(x: Int|Float) -> Float

Return the natural logarithm (base e) of a number.

log(math_e())  // 1.0
log2(x: Int|Float) -> Float

Return the base-2 logarithm of a number.

log2(8)  // 3.0
log10(x: Int|Float) -> Float

Return the base-10 logarithm of a number.

log10(1000)  // 3.0
sin(x: Int|Float) -> Float

Return the sine of an angle in radians.

sin(0)  // 0.0
cos(x: Int|Float) -> Float

Return the cosine of an angle in radians.

cos(0)  // 1.0
tan(x: Int|Float) -> Float

Return the tangent of an angle in radians.

tan(0)  // 0.0
atan2(y: Int|Float, x: Int|Float) -> Float

Return the two-argument arctangent in radians.

atan2(1, 1)  // 0.7853...
clamp(x: Int|Float, lo: Int|Float, hi: Int|Float) -> Int|Float

Clamp a value between a minimum and maximum.

clamp(15, 0, 10)  // 10
math_pi() -> Float

Return the mathematical constant pi.

math_pi()  // 3.14159265358979...
math_e() -> Float

Return Euler's number (e).

math_e()  // 2.71828182845904...
asin(x: Int|Float) -> Float

Return the arcsine in radians.

asin(1)  // 1.5707...
acos(x: Int|Float) -> Float

Return the arccosine in radians.

acos(1)  // 0.0
atan(x: Int|Float) -> Float

Return the arctangent in radians.

atan(1)  // 0.7853...
exp(x: Int|Float) -> Float

Return e raised to the power of x.

exp(1)  // 2.71828...
sign(x: Int|Float) -> Int

Return -1, 0, or 1 indicating the sign of a number.

sign(-42)  // -1
gcd(a: Int, b: Int) -> Int

Return the greatest common divisor of two integers.

gcd(12, 8)  // 4
lcm(a: Int, b: Int) -> Int

Return the least common multiple of two integers.

lcm(4, 6)  // 12
float_to_bits(x: Float) -> Int

Reinterpret a float as its IEEE 754 bit pattern (64-bit integer).

float_to_bits(1.0)  // 4607182418800017408
bits_to_float(x: Int) -> Float

Reinterpret a 64-bit integer as an IEEE 754 float.

bits_to_float(4607182418800017408)  // 1.0
is_nan(x: Int|Float) -> Bool

Check if a value is NaN (not a number).

is_nan(0.0 / 0.0)  // true
is_inf(x: Int|Float) -> Bool

Check if a value is positive or negative infinity.

is_inf(1.0 / 0.0)  // true
sinh(x: Int|Float) -> Float

Return the hyperbolic sine.

sinh(1)  // 1.1752...
cosh(x: Int|Float) -> Float

Return the hyperbolic cosine.

cosh(0)  // 1.0
tanh(x: Int|Float) -> Float

Return the hyperbolic tangent.

tanh(0)  // 0.0
lerp(a: Int|Float, b: Int|Float, t: Int|Float) -> Float

Linear interpolation between a and b by factor t.

lerp(0, 10, 0.5)  // 5.0

String Formatting

format(fmt: String, args: Any...) -> String

Format a string with placeholders replaced by arguments.

format("{} is {}", "sky", "blue")  // "sky is blue"

Regex

regex_match(pattern: String, str: String, flags?: String) -> Bool

Test if a string matches a regular expression pattern. Optional flags: "i" (case-insensitive), "m" (multiline).

regex_match("^[0-9]+$", "123")  // true
regex_match("[a-z]+", "HELLO", "i")  // true
regex_find_all(pattern: String, str: String, flags?: String) -> Array

Find all matches of a pattern in a string, returning an array. Optional flags: "i" (case-insensitive), "m" (multiline).

regex_find_all("[0-9]+", "a1b2c3")  // ["1", "2", "3"]
regex_replace(pattern: String, str: String, replacement: String, flags?: String) -> String

Replace all matches of a pattern in a string. Optional flags: "i" (case-insensitive), "m" (multiline).

regex_replace("[0-9]", "a1b2", "X")  // "aXbX"
regex_replace("hello", "HELLO world", "hi", "i")  // "hi world"

JSON

json_parse(s: String) -> Any

Parse a JSON string into a Lattice value.

json_parse("{\"a\": 1}")  // {a: 1}
json_stringify(val: Any) -> String

Serialize a Lattice value to a JSON string.

json_stringify([1, 2, 3])  // "[1,2,3]"

CSV

csv_parse(s: String) -> Array

Parse a CSV string into an array of arrays (rows of fields).

csv_parse("a,b\n1,2")  // [["a", "b"], ["1", "2"]]
csv_stringify(rows: Array) -> String

Convert an array of arrays into a CSV string.

csv_stringify([["a", "b"], ["1", "2"]])  // "a,b\n1,2\n"

URL

url_encode(s: String) -> String

Percent-encode a string for use in URLs.

url_encode("hello world")  // "hello%20world"
url_decode(s: String) -> String

Decode a percent-encoded URL string.

url_decode("hello%20world")  // "hello world"

HTTP

http_get(url: String) -> Map

Perform an HTTP GET request. Returns a map with "status", "headers", and "body".

http_get("https://httpbin.org/get")
http_post(url: String, options: Map) -> Map

Perform an HTTP POST request. Options map may contain "headers" (Map), "body" (String), and "timeout" (Int ms).

http_post("https://httpbin.org/post", {"body": "hello"})
http_request(method: String, url: String, options?: Map) -> Map

Perform an HTTP request with a custom method. Options may contain "headers", "body", and "timeout".

http_request("PUT", "https://api.example.com/data", {"body": "{}"})

Data Formats

toml_parse(s: String) -> Map

Parse a TOML string into a Lattice Map.

toml_parse("[server]\nhost = \"localhost\"\nport = 8080")
toml_stringify(val: Map) -> String

Serialize a Lattice Map to a TOML string.

toml_stringify({"host": "localhost", "port": 8080})
yaml_parse(s: String) -> Map|Array

Parse a YAML string into a Lattice value.

yaml_parse("name: Alice\nage: 30")
yaml_stringify(val: Map|Array) -> String

Serialize a Lattice value to a YAML string.

yaml_stringify({"name": "Alice", "age": 30})

Functional

identity(val: Any) -> Any

Return the argument unchanged.

identity(42)  // 42
pipe(val: Any, fns: Closure...) -> Any

Thread a value through a series of functions left to right.

pipe(5, |x| { x * 2 }, |x| { x + 1 })  // 11
compose(f: Closure, g: Closure) -> Closure

Compose two functions: compose(f, g)(x) calls f(g(x)).

compose(|x| { x + 1 }, |x| { x * 2 })(3)  // 7

Metaprogramming

is_complete(source: String) -> Bool

Check if a source string is a complete expression (balanced brackets).

is_complete("{ 1 + 2 }")  // true
require(path: String) -> Bool

Load and execute a Lattice source file, importing its definitions.

require("stdlib.lat")  // true
require_ext(name: String) -> Map

Load a native extension (.dylib/.so) and return a Map of its functions.

let pg = require_ext("pg")
lat_eval(source: String) -> Any

Parse and execute a string as Lattice source code, returning the result.

lat_eval("1 + 2")  // 3
tokenize(source: String) -> Array

Tokenize a source string, returning an array of Token structs.

tokenize("1 + 2")  // [{type: "INT_LIT", text: "1"}, ...]

File System

read_file(path: String) -> String

Read the entire contents of a file as a string.

read_file("data.txt")  // "file contents..."
write_file(path: String, content: String) -> Bool

Write a string to a file, creating or overwriting it.

write_file("out.txt", "hello")  // true
file_exists(path: String) -> Bool

Check if a file or directory exists at the given path.

file_exists("data.txt")  // true
delete_file(path: String) -> Bool

Delete a file at the given path.

delete_file("temp.txt")  // true
list_dir(path: String) -> Array

List entries in a directory, returning an array of filenames.

list_dir(".")  // ["file1.txt", "dir1", ...]
read_file_bytes(path: String) -> Buffer

Read the entire contents of a file as a Buffer.

read_file_bytes("data.bin")  // Buffer<...>
write_file_bytes(path: String, buffer: Buffer) -> Bool

Write a Buffer to a file.

write_file_bytes("out.bin", buf)  // true
append_file(path: String, content: String) -> Bool

Append a string to the end of a file.

append_file("log.txt", "new line\n")  // true
mkdir(path: String) -> Bool

Create a directory at the given path.

mkdir("new_dir")  // true
rename(old_path: String, new_path: String) -> Bool

Rename or move a file or directory.

rename("old.txt", "new.txt")  // true
is_dir(path: String) -> Bool

Check if the path points to a directory.

is_dir("/tmp")  // true
is_file(path: String) -> Bool

Check if the path points to a regular file.

is_file("data.txt")  // true
rmdir(path: String) -> Bool

Remove a directory (must be empty).

rmdir("old_dir")  // true
glob(pattern: String) -> Array

Find files matching a glob pattern, returning an array of paths.

glob("*.txt")  // ["a.txt", "b.txt"]
stat(path: String) -> Map

Get file metadata (size, mtime, type, permissions) as a map.

stat("file.txt")  // {size: 1024, mtime: ..., type: "file", permissions: 644}
copy_file(src: String, dest: String) -> Bool

Copy a file from source path to destination path.

copy_file("a.txt", "b.txt")  // true
realpath(path: String) -> String

Resolve a path to its absolute canonical form.

realpath("./src/../src")  // "/home/user/src"
tempdir() -> String

Create a temporary directory and return its path.

tempdir()  // "/tmp/lat_XXXXXX"
tempfile() -> String

Create a temporary file and return its path.

tempfile()  // "/tmp/lat_XXXXXX"
chmod(path: String, mode: Int) -> Bool

Change file permissions using a numeric mode.

chmod("script.sh", 755)  // true
file_size(path: String) -> Int

Return the size of a file in bytes.

file_size("data.bin")  // 4096

Path

path_join(parts: String...) -> String

Join path components into a single path string.

path_join("/home", "user", "file.txt")  // "/home/user/file.txt"
path_dir(path: String) -> String

Return the directory component of a path.

path_dir("/home/user/file.txt")  // "/home/user"
path_base(path: String) -> String

Return the filename component of a path.

path_base("/home/user/file.txt")  // "file.txt"
path_ext(path: String) -> String

Return the file extension of a path (including the dot).

path_ext("file.txt")  // ".txt"

Environment

env(name: String) -> String|Unit

Get an environment variable's value, or unit if not set.

env("HOME")  // "/home/user"
env_set(name: String, value: String) -> Unit

Set an environment variable.

env_set("MY_VAR", "hello")
env_keys() -> Array

Return an array of all environment variable names.

env_keys()  // ["HOME", "PATH", ...]

Process

cwd() -> String

Return the current working directory.

cwd()  // "/home/user/project"
exec(cmd: String) -> Map

Execute a command directly (no shell), returning {stdout, stderr, status}.

exec("ls -la")  // {stdout: "...", stderr: "", status: 0}
shell(cmd: String) -> Map

Execute a command via the system shell, returning {stdout, stderr, status}.

shell("echo hello")  // {stdout: "hello\n", stderr: "", status: 0}
args() -> Array

Return command-line arguments as an array of strings.

args()  // ["script.lat", "--flag"]
platform() -> String

Return the operating system name ("darwin", "linux", etc.).

platform()  // "darwin"
hostname() -> String

Return the system hostname.

hostname()  // "my-machine"
pid() -> Int

Return the current process ID.

pid()  // 12345

Date & Time

time() -> Int

Return the current Unix timestamp in milliseconds.

time()  // 1700000000000
sleep(ms: Int) -> Unit

Pause execution for the given number of milliseconds.

sleep(1000)  // sleeps for 1 second
time_format(epoch_ms: Int, fmt: String) -> String

Format a Unix timestamp (ms) using a strftime format string.

time_format(0, "%Y-%m-%d")  // "1970-01-01"
time_parse(datetime: String, fmt: String) -> Int

Parse a datetime string into a Unix timestamp (ms).

time_parse("2024-01-01", "%Y-%m-%d")  // 1704067200000
time_year(epoch_ms: Int) -> Int

Extract the year from a timestamp.

time_year(0)  // 1970
time_month(epoch_ms: Int) -> Int

Extract the month (1-12) from a timestamp.

time_month(0)  // 1
time_day(epoch_ms: Int) -> Int

Extract the day of month (1-31) from a timestamp.

time_day(0)  // 1
time_hour(epoch_ms: Int) -> Int

Extract the hour (0-23) from a timestamp.

time_hour(0)  // 0
time_minute(epoch_ms: Int) -> Int

Extract the minute (0-59) from a timestamp.

time_minute(0)  // 0
time_second(epoch_ms: Int) -> Int

Extract the second (0-59) from a timestamp.

time_second(0)  // 0
time_weekday(epoch_ms: Int) -> Int

Extract the day of week (0=Sunday, 6=Saturday) from a timestamp.

time_weekday(0)  // 4
time_add(epoch_ms: Int, delta_ms: Int) -> Int

Add milliseconds to a timestamp.

time_add(0, 86400000)  // 86400000
is_leap_year(year: Int) -> Bool

Check if a year is a leap year.

is_leap_year(2024)  // true
days_in_month(year: Int, month: Int) -> Int

Number of days in the given month of the given year.

days_in_month(2024, 2)  // 29
day_of_week(year: Int, month: Int, day: Int) -> Int

Day of week (0=Sunday, 6=Saturday).

day_of_week(2026, 2, 24)  // 2
day_of_year(year: Int, month: Int, day: Int) -> Int

Day of year (1-366).

day_of_year(2026, 2, 24)  // 55
timezone_offset() -> Int

Current local timezone offset from UTC in seconds.

duration(hours: Int, minutes: Int, seconds: Int, millis: Int) -> Map

Create a Duration map.

duration_from_seconds(s: Int) -> Map

Create a Duration from total seconds.

duration_from_millis(ms: Int) -> Map

Create a Duration from total milliseconds.

duration_add(d1: Map, d2: Map) -> Map

Add two Duration maps.

duration_sub(d1: Map, d2: Map) -> Map

Subtract Duration d2 from d1.

duration_to_string(d: Map) -> String

Format a Duration as "2h 30m 15s".

duration_hours(d: Map) -> Int

Extract hours from a Duration.

duration_minutes(d: Map) -> Int

Extract minutes from a Duration.

duration_seconds(d: Map) -> Int

Extract seconds from a Duration.

duration_millis(d: Map) -> Int

Extract millis from a Duration.

datetime_now() -> Map

Returns DateTime map with current local time.

datetime_from_epoch(epoch_seconds: Int) -> Map

Create DateTime from epoch seconds (UTC).

datetime_to_epoch(dt: Map) -> Int

Convert DateTime map to epoch seconds.

datetime_from_iso(str: String) -> Map

Parse ISO 8601 string into DateTime map.

datetime_to_iso(dt: Map) -> String

Format DateTime map as ISO 8601 string.

datetime_add_duration(dt: Map, dur: Map) -> Map

Add Duration to DateTime.

datetime_sub(dt1: Map, dt2: Map) -> Map

Subtract two DateTimes, returning a Duration.

datetime_format(dt: Map, fmt: String) -> String

Format DateTime using strftime-style format.

datetime_to_utc(dt: Map) -> Map

Convert DateTime to UTC.

datetime_to_local(dt: Map) -> Map

Convert DateTime to local timezone.

duration(hours: Int, minutes: Int, seconds: Int, millis: Int) -> Map

Create a Duration map with hours, minutes, seconds, millis fields.

duration(2, 30, 15, 0)  // {hours: 2, minutes: 30, seconds: 15, millis: 0, total_ms: 9015000}
duration_from_seconds(s: Int) -> Map

Create a Duration from total seconds.

duration_from_seconds(3661)  // {hours: 1, minutes: 1, seconds: 1, ...}
duration_from_millis(ms: Int) -> Map

Create a Duration from total milliseconds.

duration_from_millis(5000)  // {hours: 0, minutes: 0, seconds: 5, ...}
duration_add(d1: Map, d2: Map) -> Map

Add two Duration maps.

duration_sub(d1: Map, d2: Map) -> Map

Subtract Duration d2 from d1.

duration_to_string(d: Map) -> String

Format a Duration map as a human-readable string like "2h 30m 15s".

duration_to_string(duration(2, 30, 15, 0))  // "2h 30m 15s"
duration_hours(d: Map) -> Int

Extract the hours component from a Duration.

duration_minutes(d: Map) -> Int

Extract the minutes component from a Duration.

duration_seconds(d: Map) -> Int

Extract the seconds component from a Duration.

duration_millis(d: Map) -> Int

Extract the millis component from a Duration.

datetime_now() -> Map

Returns a DateTime map with current local time components.

datetime_now()  // {year: 2026, month: 2, day: 24, hour: 10, ...}
datetime_from_epoch(epoch_seconds: Int) -> Map

Create a DateTime map from epoch seconds (UTC).

datetime_from_epoch(0)  // {year: 1970, month: 1, day: 1, hour: 0, ...}
datetime_to_epoch(dt: Map) -> Int

Convert a DateTime map to epoch seconds.

datetime_from_iso(str: String) -> Map

Parse an ISO 8601 string into a DateTime map.

datetime_from_iso("2026-02-24T10:30:00Z")
datetime_to_iso(dt: Map) -> String

Format a DateTime map as an ISO 8601 string.

datetime_to_iso(datetime_from_epoch(0))  // "1970-01-01T00:00:00Z"
datetime_add_duration(dt: Map, dur: Map) -> Map

Add a Duration to a DateTime, returning a new DateTime.

datetime_sub(dt1: Map, dt2: Map) -> Map

Subtract two DateTimes, returning a Duration.

datetime_format(dt: Map, fmt: String) -> String

Format a DateTime map using strftime-style format.

datetime_format(datetime_from_epoch(0), "%Y-%m-%d")  // "1970-01-01"
datetime_to_utc(dt: Map) -> Map

Convert a DateTime to UTC (tz_offset becomes 0).

datetime_to_local(dt: Map) -> Map

Convert a DateTime to the local timezone.

timezone_offset() -> Int

Returns the current local timezone offset from UTC in seconds.

days_in_month(year: Int, month: Int) -> Int

Returns the number of days in the given month of the given year.

days_in_month(2024, 2)  // 29
day_of_week(year: Int, month: Int, day: Int) -> Int

Returns the day of week (0=Sunday, 6=Saturday).

day_of_week(2026, 2, 24)  // 2 (Tuesday)
day_of_year(year: Int, month: Int, day: Int) -> Int

Returns the day of year (1-366).

day_of_year(2026, 2, 24)  // 55

Crypto

sha256(s: String) -> String

Compute the SHA-256 hash of a string, returned as hex.

sha256("hello")  // "2cf24dba..."
md5(s: String) -> String

Compute the MD5 hash of a string, returned as hex.

md5("hello")  // "5d41402a..."
base64_encode(s: String) -> String

Encode a string to Base64.

base64_encode("hello")  // "aGVsbG8="
base64_decode(s: String) -> String

Decode a Base64 string.

base64_decode("aGVsbG8=")  // "hello"
sha512(s: String) -> String

Compute the SHA-512 hash of a string, returned as hex.

sha512("hello")  // "9b71d224..."
hmac_sha256(key: String, data: String) -> String

Compute the HMAC-SHA256 of data with key, returned as hex.

hmac_sha256("secret", "hello")  // "88aab3ed..."
random_bytes(n: Int) -> Buffer

Generate n cryptographically secure random bytes.

random_bytes(16).length()  // 16
uuid() -> String

Generate an RFC 4122 version 4 random UUID.

uuid()  // "550e8400-e29b-41d4-a716-446655440000"
uuid() -> String

Generate an RFC 4122 version 4 random UUID.

Networking

tcp_listen(host: String, port: Int) -> Int

Create a TCP server socket listening on host:port, returning a file descriptor.

tcp_listen("0.0.0.0", 8080)  // 3
tcp_accept(server_fd: Int) -> Int

Accept an incoming TCP connection, returning a new client file descriptor.

tcp_accept(server_fd)  // 4
tcp_connect(host: String, port: Int) -> Int

Connect to a TCP server, returning a file descriptor.

tcp_connect("localhost", 8080)  // 3
tcp_read(fd: Int) -> String

Read data from a TCP socket as a string.

tcp_read(client_fd)  // "HTTP/1.1 200 OK..."
tcp_read_bytes(fd: Int, n: Int) -> String

Read exactly n bytes from a TCP socket.

tcp_read_bytes(fd, 1024)  // "..."
tcp_write(fd: Int, data: String) -> Bool

Write a string to a TCP socket.

tcp_write(fd, "GET / HTTP/1.1\r\n\r\n")  // true
tcp_close(fd: Int) -> Unit

Close a TCP socket.

tcp_close(fd)
tcp_peer_addr(fd: Int) -> String

Get the remote address of a connected TCP socket.

tcp_peer_addr(client_fd)  // "192.168.1.1:54321"
tcp_set_timeout(fd: Int, secs: Int) -> Bool

Set read/write timeout on a TCP socket in seconds.

tcp_set_timeout(fd, 30)  // true
tls_connect(host: String, port: Int) -> Int

Establish a TLS connection to a server, returning a handle.

tls_connect("example.com", 443)  // 1
tls_read(handle: Int) -> String

Read data from a TLS connection as a string.

tls_read(handle)  // "HTTP/1.1 200 OK..."
tls_read_bytes(handle: Int, n: Int) -> String

Read exactly n bytes from a TLS connection.

tls_read_bytes(handle, 512)  // "..."
tls_write(handle: Int, data: String) -> Bool

Write a string to a TLS connection.

tls_write(handle, "GET / HTTP/1.1\r\n\r\n")  // true
tls_close(handle: Int) -> Unit

Close a TLS connection.

tls_close(handle)
tls_available() -> Bool

Check if TLS support is available (OpenSSL linked).

tls_available()  // true

String Methods

String.contains(substr: String) -> Bool

Check if the string contains a substring.

"hello world".contains("world")  // true
String.starts_with(prefix: String) -> Bool

Check if the string starts with the given prefix.

"hello".starts_with("he")  // true
String.ends_with(suffix: String) -> Bool

Check if the string ends with the given suffix.

"hello".ends_with("lo")  // true
String.trim() -> String

Remove leading and trailing whitespace.

"  hello  ".trim()  // "hello"
String.to_upper() -> String

Convert the string to uppercase.

"hello".to_upper()  // "HELLO"
String.to_lower() -> String

Convert the string to lowercase.

"HELLO".to_lower()  // "hello"
String.capitalize() -> String

Capitalize the first letter, lowercase the rest.

"hello world".capitalize()  // "Hello world"
String.title_case() -> String

Capitalize the first letter of each word.

"hello world".title_case()  // "Hello World"
String.snake_case() -> String

Convert to snake_case.

"helloWorld".snake_case()  // "hello_world"
String.camel_case() -> String

Convert to camelCase.

"hello_world".camel_case()  // "helloWorld"
String.kebab_case() -> String

Convert to kebab-case.

"helloWorld".kebab_case()  // "hello-world"
String.replace(old: String, new: String) -> String

Replace all occurrences of a substring.

"hello world".replace("world", "there")  // "hello there"
String.split(sep: String) -> Array

Split the string by a separator, returning an array of parts.

"a,b,c".split(",")  // ["a", "b", "c"]
String.index_of(substr: String) -> Int

Return the index of the first occurrence of substr, or -1 if not found.

"hello".index_of("ll")  // 2
String.substring(start: Int, end: Int) -> String

Extract a substring from start (inclusive) to end (exclusive).

"hello".substring(1, 4)  // "ell"
String.chars() -> Array

Split the string into an array of single-character strings.

"abc".chars()  // ["a", "b", "c"]
String.bytes() -> Array

Return an array of byte values (integers) for the string.

"AB".bytes()  // [65, 66]
String.reverse() -> String

Return the string with characters in reverse order.

"hello".reverse()  // "olleh"
String.repeat(n: Int) -> String

Repeat the string n times.

"ab".repeat(3)  // "ababab"
String.trim_start() -> String

Remove leading whitespace.

"  hello".trim_start()  // "hello"
String.trim_end() -> String

Remove trailing whitespace.

"hello  ".trim_end()  // "hello"
String.pad_left(n: Int, ch: String) -> String

Pad the string on the left to reach length n using character ch.

"42".pad_left(5, "0")  // "00042"
String.pad_right(n: Int, ch: String) -> String

Pad the string on the right to reach length n using character ch.

"42".pad_right(5, "0")  // "42000"
String.count(substr: String) -> Int

Count non-overlapping occurrences of a substring.

"ababa".count("ab")  // 2
String.is_empty() -> Bool

Check if the string is empty.

"".is_empty()  // true

Array Methods

Array.contains(val: Any) -> Bool

Check whether the array contains an element equal to val.

[1, 2, 3].contains(2)  // true
Array.enumerate() -> Array

Return an array of [index, value] pairs.

["a", "b"].enumerate()  // [[0, "a"], [1, "b"]]
Array.reverse() -> Array

Return a new array with elements in reverse order.

[1, 2, 3].reverse()  // [3, 2, 1]
Array.join(sep: String) -> String

Join all elements into a string separated by sep.

[1, 2, 3].join(", ")  // "1, 2, 3"
Array.unique() -> Array

Return a new array with duplicate elements removed.

[1, 2, 2, 3].unique()  // [1, 2, 3]
Array.index_of(val: Any) -> Int

Return the index of the first occurrence of val, or -1 if not found.

[10, 20, 30].index_of(20)  // 1
Array.zip(other: Array) -> Array

Pair elements from two arrays into an array of [a, b] pairs.

[1, 2].zip(["a", "b"])  // [[1, "a"], [2, "b"]]
Array.sum() -> Int|Float

Return the sum of all numeric elements in the array.

[1, 2, 3].sum()  // 6
Array.min() -> Int|Float

Return the smallest numeric element in the array.

[3, 1, 2].min()  // 1
Array.max() -> Int|Float

Return the largest numeric element in the array.

[3, 1, 2].max()  // 3
Array.first() -> Any|Unit

Return the first element, or unit if the array is empty.

[10, 20].first()  // 10
Array.last() -> Any|Unit

Return the last element, or unit if the array is empty.

[10, 20].last()  // 20
Array.take(n: Int) -> Array

Return a new array with the first n elements.

[1, 2, 3, 4].take(2)  // [1, 2]
Array.drop(n: Int) -> Array

Return a new array with the first n elements removed.

[1, 2, 3, 4].drop(2)  // [3, 4]
Array.chunk(size: Int) -> Array

Split the array into sub-arrays of the given size.

[1, 2, 3, 4, 5].chunk(2)  // [[1, 2], [3, 4], [5]]
Array.flatten() -> Array

Flatten one level of nested arrays into a single array.

[[1, 2], [3]].flatten()  // [1, 2, 3]
Array.map(fn: Closure) -> Array

Apply fn to each element and return a new array of results.

[1, 2, 3].map(|x| x * 2)  // [2, 4, 6]
Array.filter(fn: Closure) -> Array

Return a new array containing only elements for which fn returns true.

[1, 2, 3, 4].filter(|x| x > 2)  // [3, 4]
Array.reduce(fn: Closure, init: Any) -> Any

Reduce the array to a single value by applying fn(accumulator, element) from left to right.

[1, 2, 3].reduce(|a, b| a + b, 0)  // 6
Array.each(fn: Closure) -> Unit

Call fn for each element in the array (side-effects only, returns unit).

[1, 2, 3].each(|x| print(x))
Array.find(fn: Closure) -> Any|Unit

Return the first element for which fn returns true, or unit if none match.

[1, 2, 3].find(|x| x > 1)  // 2
Array.any(fn: Closure) -> Bool

Return true if fn returns true for at least one element.

[1, 2, 3].any(|x| x > 2)  // true
Array.all(fn: Closure) -> Bool

Return true if fn returns true for every element.

[2, 4, 6].all(|x| x % 2 == 0)  // true
Array.flat_map(fn: Closure) -> Array

Map each element with fn, then flatten one level. Equivalent to map then flatten.

[1, 2].flat_map(|x| [x, x * 10])  // [1, 10, 2, 20]
Array.sort_by(cmp: Closure) -> Array

Return a new array sorted using the comparator closure. cmp(a, b) should return negative if a < b.

[3, 1, 2].sort_by(|a, b| a - b)  // [1, 2, 3]
Array.group_by(fn: Closure) -> Map

Group elements into a map keyed by the result of fn applied to each element.

[1, 2, 3, 4].group_by(|x| x % 2)  // {"1": [1, 3], "0": [2, 4]}
Array.push(val: Any) -> Unit

Append a value to the end of the array (mutates in place).

arr.push(42)
Array.len() -> Int

@method String.len() -> Int @method Map.len() -> Int Return the number of elements or characters. Also available as .length().

[1, 2, 3].len()  // 3
"hello".length()  // 5
Array.map(fn: Closure) -> Array

Apply a function to each element, returning a new array of results.

[1, 2, 3].map(|x| { x * 2 })  // [2, 4, 6]
Array.join(sep?: String) -> String

Join array elements into a string with an optional separator.

["a", "b", "c"].join(", ")  // "a, b, c"
Array.filter(fn: Closure) -> Array

Return a new array containing only elements for which fn returns true.

[1, 2, 3, 4].filter(|x| { x > 2 })  // [3, 4]
Array.for_each(fn: Closure) -> Unit

Call a function for each element (for side effects).

[1, 2, 3].for_each(|x| { print(x) })
Array.find(fn: Closure) -> Any|Unit

Return the first element for which fn returns true, or unit if not found.

[1, 2, 3].find(|x| { x > 1 })  // 2
Array.contains(val: Any) -> Bool

Check if the array contains a value.

[1, 2, 3].contains(2)  // true
Array.reverse() -> Array

Return a new array with elements in reverse order.

[1, 2, 3].reverse()  // [3, 2, 1]
Array.enumerate() -> Array

Return an array of [index, value] pairs.

["a", "b"].enumerate()  // [[0, "a"], [1, "b"]]
Array.sort() -> Array

Return a new sorted array (elements must be comparable).

[3, 1, 2].sort()  // [1, 2, 3]
Array.flat() -> Array

Flatten one level of nested arrays.

[[1, 2], [3, 4]].flat()  // [1, 2, 3, 4]
Array.reduce(fn: Closure, init: Any) -> Any

Reduce an array to a single value by applying fn(acc, elem) for each element.

[1, 2, 3].reduce(|a, b| { a + b }, 0)  // 6
Array.slice(start: Int, end: Int) -> Array

Return a sub-array from start (inclusive) to end (exclusive).

[1, 2, 3, 4, 5].slice(1, 4)  // [2, 3, 4]
Array.take(n: Int) -> Array

Return the first n elements of the array.

[1, 2, 3, 4].take(2)  // [1, 2]
Array.drop(n: Int) -> Array

Return the array with the first n elements removed.

[1, 2, 3, 4].drop(2)  // [3, 4]
Array.pop() -> Any

Remove and return the last element of the array.

[1, 2, 3].pop()  // 3
Array.index_of(val: Any) -> Int

Return the index of the first occurrence of val, or -1 if not found.

[10, 20, 30].index_of(20)  // 1
Array.any(fn: Closure) -> Bool

Return true if fn returns true for any element.

[1, 2, 3].any(|x| { x > 2 })  // true
Array.all(fn: Closure) -> Bool

Return true if fn returns true for all elements.

[2, 4, 6].all(|x| { x % 2 == 0 })  // true
Array.zip(other: Array) -> Array

Combine two arrays into an array of [a, b] pairs.

[1, 2].zip(["a", "b"])  // [[1, "a"], [2, "b"]]
Array.unique() -> Array

Return a new array with duplicate elements removed.

[1, 2, 2, 3, 1].unique()  // [1, 2, 3]
Array.insert(index: Int, val: Any) -> Unit

Insert a value at the given index (mutates in place).

arr.insert(1, "x")
Array.remove_at(index: Int) -> Any

Remove and return the element at the given index.

[1, 2, 3].remove_at(1)  // 2
Array.sort_by(cmp: Closure) -> Array

Sort using a custom comparator that returns a negative, zero, or positive Int.

["bb", "a", "ccc"].sort_by(|a, b| { len(a) - len(b) })  // ["a", "bb", "ccc"]
Array.flat_map(fn: Closure) -> Array

Map each element to an array, then flatten one level.

[1, 2].flat_map(|x| { [x, x * 10] })  // [1, 10, 2, 20]
Array.chunk(size: Int) -> Array

Split the array into sub-arrays of the given size.

[1, 2, 3, 4, 5].chunk(2)  // [[1, 2], [3, 4], [5]]
Array.group_by(fn: Closure) -> Map

Group elements by the result of fn, returning a map of key to arrays.

[1, 2, 3, 4].group_by(|x| { x % 2 })  // {0: [2, 4], 1: [1, 3]}
Array.sum() -> Int|Float

Return the sum of all numeric elements.

[1, 2, 3].sum()  // 6
Array.min() -> Int|Float

Return the minimum element (all elements must be numeric).

[3, 1, 2].min()  // 1
Array.max() -> Int|Float

Return the maximum element (all elements must be numeric).

[3, 1, 2].max()  // 3
Array.first() -> Any|Unit

Return the first element, or unit if the array is empty.

[1, 2, 3].first()  // 1
Array.last() -> Any|Unit

Return the last element, or unit if the array is empty.

[1, 2, 3].last()  // 3

Map Methods

Map.set(key: String, value: Any) -> Unit

Set a key-value pair in the map (mutates in place).

m.set("name", "Alice")
Map.remove(key: String) -> Unit

Remove a key from the map (mutates in place).

m.remove("name")
Map.get(key: String) -> Any|Unit

Get the value for a key, or unit if not found.

m.get("name")  // "Alice"
Map.has(key: String) -> Bool

Check if the map contains the given key.

m.has("name")  // true
Map.keys() -> Array

Return an array of all keys in the map.

m.keys()  // ["name", "age"]
Map.values() -> Array

Return an array of all values in the map.

m.values()  // ["Alice", 30]
Map.len() -> Int

Return the number of key-value pairs in the map. Also available as .length().

m.len()  // 2
Map.entries() -> Array

Return an array of [key, value] pairs.

m.entries()  // [["name", "Alice"], ["age", 30]]
Map.merge(other: Map) -> Unit

Merge another map into this one (mutates in place).

m.merge(other_map)
Map.for_each(fn: Closure) -> Unit

Call fn(key, value) for each entry in the map.

m.for_each(|k, v| { print(k, v) })
Map.filter(fn: Closure) -> Map

Return a new map with only entries where fn(key, value) returns true.

m.filter(|k, v| { v > 0 })
Map.map(fn: Closure) -> Map

Return a new map with values transformed by fn(key, value).

m.map(|k, v| { v * 2 })

Set Methods

Set.add(value: Any) -> Unit

Add an element to the set (mutates in place).

s.add(42)
Set.remove(value: Any) -> Unit

Remove an element from the set (mutates in place).

s.remove(42)
Set.has(value: Any) -> Bool

Check if the set contains the value.

s.has(42)
Set.len() -> Int

Return the number of elements in the set. Also available as .length().

s.len()  // 3
Set.to_array() -> Array

Convert the set to an array of its elements.

s.to_array()
Set.union(other: Set) -> Set

Return a new set containing all elements from both sets.

s1.union(s2)
Set.intersection(other: Set) -> Set

Return a new set containing only elements in both sets.

s1.intersection(s2)
Set.difference(other: Set) -> Set

Return a new set with elements in this set but not in other.

s1.difference(s2)
Set.symmetric_difference(other: Set) -> Set

Return a new set with elements in either set but not in both.

s1.symmetric_difference(s2)
Set.is_subset(other: Set) -> Bool

Check if this set is a subset of other.

s1.is_subset(s2)
Set.is_superset(other: Set) -> Bool

Check if this set is a superset of other.

s1.is_superset(s2)

Buffer Methods

Buffer.len() -> Int

Return the number of bytes in the buffer. Also available as .length().

buf.len()  // 16
Buffer.capacity() -> Int

Return the current capacity of the buffer.

buf.capacity()
Buffer.push(byte: Int) -> Unit

Append a single byte (0-255) to the buffer.

buf.push(0x42)
Buffer.push_u16(val: Int) -> Unit

Append a 16-bit value as 2 bytes (little-endian).

buf.push_u16(0x1234)
Buffer.push_u32(val: Int) -> Unit

Append a 32-bit value as 4 bytes (little-endian).

buf.push_u32(0x12345678)
Buffer.read_u8(idx: Int) -> Int

Read a single byte at the given index.

buf.read_u8(0)
Buffer.write_u8(idx: Int, val: Int) -> Unit

Write a single byte at the given index.

buf.write_u8(0, 42)
Buffer.read_u16(idx: Int) -> Int

Read a 16-bit value (little-endian) at the given index.

buf.read_u16(0)
Buffer.write_u16(idx: Int, val: Int) -> Unit

Write a 16-bit value (little-endian) at the given index.

buf.write_u16(0, 0x1234)
Buffer.read_u32(idx: Int) -> Int

Read a 32-bit value (little-endian) at the given index.

buf.read_u32(0)
Buffer.write_u32(idx: Int, val: Int) -> Unit

Write a 32-bit value (little-endian) at the given index.

buf.write_u32(0, 0x12345678)
Buffer.read_i8(idx: Int) -> Int

Read a signed 8-bit integer at the given index.

Buffer.read_i16(idx: Int) -> Int

Read a signed 16-bit integer (little-endian) at the given index.

Buffer.read_i32(idx: Int) -> Int

Read a signed 32-bit integer (little-endian) at the given index.

Buffer.read_f32(idx: Int) -> Float

Read a 32-bit float (little-endian) at the given index.

Buffer.read_f64(idx: Int) -> Float

Read a 64-bit double (little-endian) at the given index.

Buffer.slice(start: Int, end: Int) -> Buffer

Return a new buffer containing bytes from start (inclusive) to end (exclusive).

buf.slice(0, 4)
Buffer.clear() -> Unit

Set the buffer length to 0 (capacity unchanged).

buf.clear()
Buffer.fill(byte: Int) -> Unit

Fill all bytes in the buffer with the given value.

buf.fill(0)
Buffer.resize(new_len: Int) -> Unit

Change the buffer length. New bytes are zero-filled.

buf.resize(32)
Buffer.to_string() -> String

Interpret the buffer contents as a UTF-8 string.

Buffer::from_string("hi").to_string()  // "hi"
Buffer.to_array() -> Array

Convert the buffer to an array of integers (0-255).

buf.to_array()
Buffer.to_hex() -> String

Convert the buffer contents to a hexadecimal string.

Buffer::from([0x48, 0x69]).to_hex()  // "4869"

Channel Methods

Channel.send(val: Any) -> Unit

Send a value on the channel. Crystal, unphased, and scalar values are accepted; fluid containers are rejected. Values containing Refs, closures, or iterators are rejected. Sending on a closed channel is an error.

ch.send(freeze([1, 2, 3]))
Channel.recv() -> Any|Unit

Receive a value from the channel, blocking until available. Returns unit if closed.

ch.recv()  // 42
Channel.close() -> Unit

Close the channel. Further sends raise an error; recv() returns Unit once the channel is empty.

ch.close()