Skip to content

Standard Library Reference ​

The YaoXiang standard library (std) is organized by modules; each module is imported with use and then invoked as Module.function(...). This directory contains per-module API reference documentation.

Module Index ​

ModuleExportsDescription
std.convert11Conversion of any value to String
std.dict11Dictionary read/write, key/value views, and merging
std.io7Standard output, standard input, and whole-file read/write
std.math18Integer, float, and trigonometric functions, including PI/E/TAU constants
std.string19String search, split, formatting, and parsing
std.time14Timestamps, formatting, and DateTime field access
std.result9Construction and unwrapping of Result and Error
std.range10Range iteration, predicates, and lazy adapters
std.assert1Assertions
std.net4HTTP requests and URL percent-encoding/decoding
std.concurrent3Sleep, yield scheduling, and thread identity
std.os22File handles, directories, environment variables, and working directory
std.weak2Arc / Weak weak references

Import Conventions ​

Importing a whole module:

yaoxiang
use std.list
use std.string

main: () -> Void = {
    parts = string.split("a,b,c", ",")
    println(list.len(parts))
}

You can also import by name from a module, including constants:

yaoxiang
use std.assert
use std.math.{E, PI, TAU}

main: () -> Void = {
    assert(PI > 3.14)
}

Parameter Borrowing Convention ​

A & in a signature indicates read-only auto-borrow (RFC-009 §2.8): the variable passed by the caller is not moved and can still be used after the call. This is the default shape for most read-only functions in the standard library.

yaoxiang
use std.assert
use std.list

main: () -> Void = {
    nums = [1, 2, 3]

    // All three calls only read-borrow nums; it remains usable afterward
    assert(list.len(nums) == 3)
    assert(list.len(nums) == 3)
    assert(list.contains(nums, 2))
}

A parameter without & means passed by value. Because of this, most "modifying" functions take the form of consuming the source value and returning a new one—the functional style—rather than in-place mutation:

yaoxiang
use std.assert
use std.list

main: () -> Void = {
    base = [1, 2]
    extended = list.push(base, 3)   // Returns a new list; base has been moved
    assert(list.len(extended) == 3)
}

Each module page's "Semantic Categories" section lists which functions borrow, which consume, and which mutate in place. One point deserves special attention:

Error Model ​

The standard library has two shapes of failure, each labeled in individual function entries as either "Error" or "Returns …":

ShapeBehaviorTypical scenarios
Throws runtime errorTerminates the current execution with an E6xxx codeMissing dict key E6008, index out of bounds E6003, assertion failure
Returns sentinel valueDoes not interrupt; returns Void / -1 / ""List out-of-bounds read, head of empty list, missing env var

Common runtime error codes:

CodeMeaningTrigger example
E6003Index out of boundslist.set(l, 99, v)
E6005Assertion failedassert(false)
E6007Generic runtime errorFile does not exist, result.unwrap failure
E6008Missing keydict.get(d, "nope")
E6010Integer parse failure (as Err value)string.parse_int("abc")
E6011Float parse failure (as Err value)string.parse_float("abc")

See the Error Code Reference for the full table.

string.parse_int / string.parse_float fall into a third shape: they do not throw, but wrap the failure as the Err value of a Result, which can be unwrapped with std.result or propagated with ?.

yaoxiang
use std.assert
use std.result
use std.string

main: () -> Void = {
    assert(result.is_ok(string.parse_int("42")))
    assert(result.is_err(string.parse_int("abc")))
}

Iteration Protocol ​

std.list and std.range provide the same iterator protocol. The iterator itself is a Tuple carrying the state.

Move semantics: both next and has_next move the iterator (no & in the signature), so each access requires recreating it, or simply use for ... in.

yaoxiang
use std.assert
use std.list

main: () -> Void = {
    it = list.iter([1, 2, 3])
    assert(list.has_next(it))

    // has_next has moved it; recreate it before taking the element
    it2 = list.iter([1, 2, 3])
    assert(list.next(it2) == 1)
}

For everyday traversal, just use for ... in:

yaoxiang
use std.assert

main: () -> Void = {
    mut sum = 0
    for x in [1, 2, 3] {
        sum = sum + x
    }
    assert(sum == 6)
}

range.map / range.filter return lazy adapters; they only produce results once consumed by collect / reduce / for_each / for ... in:

yaoxiang
use std.assert
use std.list
use std.range
use std.result

main: () -> Void = {
    doubled = range.collect(range.map(result.unwrap(range.iter(1..4)), x => x * 2))
    assert(list.get(doubled, 0) == 2)
    assert(list.len(doubled) == 3)
}

Platform Availability ​

The following content depends on operating system capabilities and is not exported for the wasm32 target:

ScopeRequires
All of std.os, all of std.net, all of std.weakFiles / network
All of std.concurrentThreads
std.io.read_line / read_file / write_file / append_fileStandard I/O
std.time.sleepThread sleep

std.string / std.list / std.dict / std.math / std.convert / std.result / std.range / std.assert, and std.io.print / println / format_fallback are available on all targets.

Known Gaps ​

The following issues were each confirmed by actually running the examples when the documentation was written, and are all tracked with issues.

Fixed (2026-09-19): #337 / #338 / #339 / #340 are all fixed, and the corresponding pages have been rewritten as normal usage:

LocationOriginal issueFix
os.openHandle is one-shot; open→write→close would not compileHandle now passed by reference ✅
time.datetime_*8 accessors could not be called from source (export name contained ::)Flattened to names like datetime_year ✅
time.parse_timefmt parameter was ignored; return value could not be used furtherStep-by-step parsing according to fmt ✅
math.clampmin > max would panic the interpreter instead of returning an errorReturns E6007 ✅

Still open:

LocationIssueTracking
net.http_get / http_postPlaceholder implementation; does not send a request, returns a description string#56

Documentation Maintenance ​

This directory follows a generated + handwritten hybrid structure:

  • Generated region (between the <!-- stdlib:KEY start/end --> markers): function overview tables and signature blocks, derived from StdModule::exports(). Signatures come byte-for-byte from NativeExport::signature and cannot drift from the implementation.
  • Handwritten region (outside the markers): module overviews, borrow/move semantics, the error model, known gaps, and examples.

Gates (run in CI alongside cargo test --lib):

GateTestPurpose
Drift detectiontest_stdlib_docs_match_generationGenerated region must match exports()
Orphan detectiontest_stdlib_docs_has_no_orphan_module_pagesModule pages must not exceed generator output
Coveragetest_stdlib_docs_covers_interface_modulesDocumented module set must cover the interface view
Example runnabilitytest_stdlib_docs_examples_runEvery ```yaoxiang example must actually run

After exports() changes, use the healing tool to rewrite the generated region:

bash
cargo run --example gen-stdlib-docs

It is isomorphic to gen-std-interfaces (RFC-037 interface view) and tools/code-tables --fix (RFC-013 code table).