Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Standard library

Aperio’s stdlib ships bundled with every binary — no separate install, no manual import for stdlib namespaces (just inline std::* paths in your code). This page indexes the shipped surface. The authoritative phase-by-phase history lives at spec/stdlib.md.

Two shapes

The stdlib comes in two structurally distinct shapes, with a clear rule for which is which:

Path-call dispatch

Inline calls through std::* paths that route directly to C runtime primitives. No .ap source backing them — they’re extern bridges into lotus_* C functions:

let pid     = std::process::pid();
let content = std::io::fs::read_file("config.toml");
let n       = std::str::parse_int("42");

Namespaces with path-call shape:

NamespaceSurface
std::processpid(), exit(code)
std::envargs_count(), arg(i), var(name), var_exists(name)
std::timemonotonic() → Duration, sleep(d)
std::strparse_int / can_parse_int / parse_float / can_parse_float, index_of, lower / upper, trim, replace, repeat, pad_left / pad_right, from_bytes, builder_new / builder_append / builder_len / builder_finish
std::bytesat(b, i), slice(b, lo, hi), from_string(s)
std::io::fsread_file, write_file, write_file_append, read_bytes, file_size, file_exists, mkdir, list_dir, list_dir_count, list_dir_at, read_file_status
std::mathsqrt, exp, log, floor, ceil, pow
std::tstree-sitter bindings (Go grammar shipped)

Path-call surfaces are appropriate for value-shaped operations that don’t need lifecycle. A file read returns bytes; a math op returns a number; argv access returns a string. No locus required.

Namespace lotus

When the operation has a lifetime — a stream that’s open across multiple reads, a sink that has setup and teardown — the stdlib provides a namespace lotus: an Aperio-sourced locus under runtime/stdlib/. You instantiate it the same way you instantiate any other locus:

let l = std::io::tcp::Listener {
    host: "127.0.0.1",
    port: 8080,
    on_connection: my_handler,
};

Namespaces with namespace-lotus shape:

NamespaceLoci / interfaces shipped
std::io::tcpListener, Stream, plus send / send_bytes / recv_bytes methods
std::httpRequest and Response types, parse_request, write_response, case-insensitive header lookup
std::textmd_to_html, base64::encode / decode, Sink interface with StdoutSink / StringSink / FileSink implementations
std::cliResolver for argv parsing
std::iterLines iterator over text
std::jsonBuilder for JSON output
std::langMorpheme, Vocabulary, etc. for language utilities
std::logLogger, LogEvent, StdoutSink (subscribes to log.**)
std::yamlYAML parsing surface
std::testassert(cond, msg), assert_eq_int, assert_eq_str

Source for namespace-lotus stdlib lives at crates/aperio-codegen/runtime/stdlib/. Read it directly — it’s idiomatic Aperio that exercises every pattern Concepts covers.

Built-in identifiers (no path needed)

A handful of functions and types are always in scope without any std::* qualification:

NamePurpose
print, println, eprint, eprintlnstdout / stderr output
len(x)length of String / Bytes / array
to_string(x)format any printable value to String
min(a, b), max(a, b), abs(x)numeric helpers
starts_with(s, prefix), contains(s, needle)string predicates
sum(expr), prod(expr)reductions (also closure-test primitives)
Int(x)explicit Float → Int narrowing (truncate toward zero)

Primitive types (Int, Uint, Float, Decimal, String, Bool, Time, Duration, Bytes) are valid only in type position.

Form-synthesized types

When any locus in your program uses @form(...), the resolver injects companion error types into the top scope:

FormSynthesized typeFields
@form(vec)IndexErrorkind: String, index: Int, len: Int
@form(hashmap)KeyErrorkind: String
@form(ring_buffer)EmptyErrorkind: String

You can reference these as ordinary types — pattern-match them in match, declare fn parameters typed by them, construct them in fallback expressions.

What’s NOT in stdlib

Aperio’s stdlib follows Go’s batteries-included approach: table-stakes functionality ships. Specifically not in stdlib (and intended for the aperio-lang/pond contrib monorepo or third-party):

  • ML / learning libraries
  • Database drivers (Postgres, MySQL, …)
  • Web frameworks beyond basic HTTP
  • Image / audio / video processing
  • Cloud SDKs (AWS, GCP, …)
  • GUI / TUI frameworks beyond what std::io::tcp enables
  • Cryptography beyond TLS basics
  • Compression formats beyond gzip (used internally by HTTP)

Aperio also doesn’t have parametric collection types in stdlib — no Vec<T> / Map<K, V> / Set<T> / Option<T> / Result<T, E> as user-facing tagged enums. Storage is locus-shaped via @form(...). See Capacity & storage for the rationale.

Reading order

If you’re writing application code and want to discover what’s available, the productive order is:

  1. Skim this page to know what namespaces exist.
  2. Read the spec section (spec/stdlib.md) for the namespace you need; it’s the authoritative surface.
  3. Read the namespace-lotus source for any lotus you’ll use — it’s a few hundred lines per namespace, and it’s the clearest documentation of how the surface composes.