Skip to content

Standard library overview

The dusk standard library lives under lib/std in the repository and is written in dusk itself. It is small and deliberate: console and file I/O, string helpers, two collections, allocators, two functional enums, and the concurrency modules.

Import a module with a dotted path in an @import directive at the top of the file, before declarations.

@import std.io
@import std.functional.maybe

A dotted path resolves to a module (a directory or a file) or to a leaf symbol inside a file.

@import std.io // module
@import std.io.print_line // one symbol

After a module import the module’s exported names are in scope flat, so @import std.io lets you call print_int and print_line with no prefix. A qualified call through the module path reaches the same function, so std.io.print_line("hi") also works. Enum constructors keep their type name: after @import std.functional.maybe you write Maybe.Some(42) and Maybe.None.

Imports are independent of paradigm directives. Importing a module does not grant any paradigm; a file that wants while and mut still declares @paradigm procedural itself. See Source files for the full import and export rules.

Some names need no import at all. print, println, printerr, alloc, free, read_file, write_file, read_line, read_all, spawn, join, and submit are builtins, available everywhere. See Builtins.

Every module below is in the tree today, written in dusk under lib/std.

ModuleWhat it holdsDetails
std.ioprint_int, print_line, typed line input with read_int and read_floatI/O
std.stringstr_len, str_eq, the parsers, and the growable StringBuilderStrings
std.vectorVector<T>, a growable heap arrayCollections
std.mapMap<V>, a hash map from string keys, returning Maybe<V> on lookupCollections
std.memory.allocatorThe Allocator interface with the Heap, FixedBuffer, and Debug allocatorsMemory
std.memory.arenaArena, a bump allocator reset or destroyed as a wholeMemory
std.functional.maybeMaybe<T> with is_some and unwrap_orFunctional
std.functional.eitherEither<L, R> with is_left and left_orFunctional
std.concurrent.threadsleep_ms, beside the spawn and join builtinsConcurrency
std.concurrent.atomicAtomicInt, sequentially consistent int64 atomicsConcurrency
std.concurrent.channelChannel<T>, a bounded, thread-safe queue, with try and timeout variantsConcurrency
std.concurrent.syncMutex and CondvarConcurrency
std.concurrent.poolpool_start, pool_shutdown, and ncpu for the global thread pool behind submitConcurrency

A short program that touches both collections:

stdlib_tour.dusk
@paradigm procedural
@import std.vector
@import std.map
@import std.functional.maybe
func main() -> int32 {
v: *Vector<int64> = alloc(vec_new())
mut i: int64 = 0
while i < 3 {
vec_push(v, i * 10)
i = i + 1
}
println("vector holds {} elements", vec_len(v))
println("v[2] = {}", vec_get(v, 2))
m: *Map<int64> = alloc(map_new())
map_put(m, "answer", 42)
println("answer = {}", unwrap_or(map_get(m, "answer"), 0))
vec_free(v)
free(v)
map_free(m)
free(m)
return 0
}

Both collections follow the same shape: build the value on the heap with alloc, pass it by pointer so growth persists across calls, free the backing buffer with the module’s _free function, then free the struct itself with free. StringBuilder and Arena follow the same pattern. The memory guide covers the ownership rules behind it.

These modules aren’t in the tree yet. They sketch where the library is headed, not a schedule.

  • std.functional.result: Result<T, E>, a success value or a typed error, for code that wants a typed failure channel instead of the (T, error) tuple.
  • std.functional.io: IO<T>, a monad wrapping side effecting work so it composes with do notation.
  • std.logging: structured logging with levels and output redirection, built on std.io.
  • std.memory.collector: a garbage collector exposed as an allocator, first as a conservative collector.
  • Unicode aware string operations, extending the byte oriented helpers in std.string.
  • List<T> and a wider set of helpers across Maybe, Either, and Result, so do notation reaches more shapes.

Two entries from the original plan have since shipped: std.map, and mutable strings as StringBuilder in std.string.