Skip to content

Standard library overview

The candela standard library is a set of modules you import by path. It sits on top of a smaller layer of built-in functions and methods that are always in scope without an import.

How std ships

The library ships as candela source. The toolchain installs a libs directory beside the candela executable:

  • libs/std/ holds one .cdl file per module: assert.cdl, convert.cdl, json.cdl, list.cdl, map.cdl, math.cdl, option.cdl, random.cdl, result.cdl, set.cdl, string.cdl, time.cdl.
  • libs/std_src/ holds the C sources and the compiled dynamic libraries for the three modules that call into native code: math, random, and time.

Set CANDELA_LIB_PATH to point at a different libs directory. The variable names the directory that contains std/ and std_src/, and it overrides the default location for both library imports and the automatic list prelude. A Rust host that embeds candela names it with Engine::with_lib_dir instead; see embedding.

Because the modules are ordinary source files, the compiler links the ones you import into your program. A .cdlb artifact built from a program that imports only pure-candela modules runs under candela-vm with no library directory present. The math, random, and time modules bind a dynamic library, so a .cdlb that uses them records the binding recipe and needs the libs directory when it runs; candela-vm finds it the way the compiler does, through CANDELA_LIB_PATH or beside its own binary. See artifacts.

Importing a module

A library import is a quoted path with no file extension. The resolver appends .cdl and looks the file up in the shipped library directory, never next to the importing file, so it works from any working directory:

import "std/string";

fn main() {
    print("hello".capitalize());
}

A module of free functions binds a namespace under as (import "std/json" as json; then json::parse(text)), or merges into the file's own scope under a bare import. A module of methods (string, map, the enum helpers) only needs importing; the methods then resolve on the receiver's type. Two bare imports that export the same free-function name are a compile error; use as to keep them apart. The import form is covered in full in modules.

A library import's first segment is looked up among the packages the project depends on before the library directory, so a dependency named std would shadow the standard library. Nothing else about std is special: it is the directory a library path falls back to.

Built-ins and modules

Built-in functions and methods are part of the language. print, str, json_parse, throw, arr.push(x), and s.uppercase() need no import and are available under candela-vm with nothing installed. They are listed in built-in functions.

Standard library modules are candela code layered on those built-ins. The collection, conversion, and enum modules define their helpers as methods in impl blocks (xs.sum(), s.capitalize(), "42".to_int(), o.unwrap_or(0)), and the rest are namespaced free functions (json::parse, math::sqrt).

One module is special. std/list loads automatically, so its methods work on any array with no import at all:

fn main() {
    let xs = [1, 2, 3, 4];
    print(xs.map(fn(x) { return x * 2; }));
    print(xs.sum());
}

The automatic prelude is skipped when the library directory is missing, and when your file already binds the name list.

The modules

Module What it gives you
assert Assertions that raise an error when a check fails
builtins The always-available functions and methods (no import)
convert to_int, to_float, to_string, to_bool methods over the built-in conversions
json Parse a json string into candela values, and serialise back
list Reductions, slicing, and higher-order methods on arrays
map Extra map methods: is_empty and get_or
math Trigonometry, logarithms, roots, rounding, and the constants
option The Option enum: Some(x) or None, with methods
random A seedable pseudo-random generator for ints and floats
result The Result enum: Ok(v) or Err(e), with methods
set Set<T>, a set of unique values, with union, intersection, difference, and symmetric difference
string Substrings, characters, padding, capitalisation, line splitting, counting
time The current unix time, and formatting a timestamp

Errors

Standard library functions report failure the same way the rest of the language does: they raise an error that stops the run and prints a message naming the cause. Each page below states what its functions raise.

A raised error carries a short code as well as a message. The code is what a catch binds and what catch "code" filters on; the message is what an uncaught error prints. A throw is its own code, so throw("no such user") is caught as no such user. A try catches what a library function raises just as it catches a throw written in the block. See error handling for the mechanism and the error catalogue for the codes.