A tour of the standard library
You've met the language. Now meet the library. Most real programs spend their time calling standard-library functions — parsing input, transforming collections, reading files, talking JSON. This chapter is a guided walk through the pieces you'll reach for most.
One rule up front: `string` and `Vector<T>` are built in (always available), and everything else needs an `import`. The import path mirrors the file: stdlib::hashmap is one module, stdlib::math another.
Strings
string methods need no import. The ones you'll use constantly:
let s: string = " Hello, Glide ";
println!(s.trim()); // "Hello, Glide"
println!(s.trim().to_lower()); // "hello, glide"
println!(s.contains("Glide")); // true
println!(s.replace("Glide", "World")); // " Hello, World "
let csv: string = "a,b,c";
let parts: *Vector<string> = csv.split(","); // ["a", "b", "c"]
println!(parts.len()); // 3
Parsing numbers out of text comes in two flavours: a hard parse_int (returns 0 on garbage) and a safe try_parse_int (returns !i32 so you can handle the failure):
let n: i32 = "42".parse_int(); // 42
let r: !i32 = "oops".try_parse_int(); // err(...)
if r.ok { println!(r.val); } else { println!("not a number"); }
Vectors
Vector<T> is the workhorse collection — built in, growable, owns its contents. Beyond push / get / len, it carries a full functional toolkit:
let v: *Vector<i32> = Vector::new();
v.push_all!(1, 2, 3, 4, 5);
let doubled: *Vector<i32> = v.map(double); // [2,4,6,8,10]
let evens: *Vector<i32> = v.filter(is_even); // [2,4]
let total: i32 = v.fold(0, add); // 15
println!(v.sum()); // 15 (Vector<i32> only)
fn double(x: i32) -> i32 { return x * 2; }
fn is_even(x: i32) -> bool { return x % 2 == 0; }
fn add(acc: i32, x: i32) -> i32 { return acc + x; }
map, filter, fold, take, skip, any, all, find, reverse, extend — they take plain function pointers (no closures yet). For a Vector<string>, .join(sep) glues it back into one string:
let words: *Vector<string> = Vector::new();
words.push_all!("rock", "the", "casbah");
println!(words.join(" ")); // "rock the casbah"
HashMaps
HashMap<V> is a string-keyed hash table; the value is any type V. Import it:
import stdlib::hashmap::*;
fn main() -> i32 {
let scores: *HashMap<i32> = HashMap::new();
scores.insert("alice", 30);
scores.insert("bob", 25);
if scores.contains("alice") {
println!("alice:", scores.get("alice")); // 30
}
for k in scores.keys() {
println!(k, "=>", scores.get(k));
}
return 0;
}
insert, get, contains, remove, len, keys(), values(), and entries() (a *Vector<*Pair<string, V>>) cover almost everything. Keys are always string.
Math
stdlib::math has the numeric helpers that aren't operators:
import stdlib::math::*;
fn main() -> i32 {
println!(ipow(2, 10)); // 1024 (integer power)
println!(gcd(48, 36)); // 12
println!(abs_int(-7)); // 7
println!(max_int(3, 9)); // 9
println!(min_f64(1.5, 2.5)); // 1.5
return 0;
}
Time
stdlib::time gives you a Duration type and clock access:
import stdlib::time::*;
fn main() -> i32 {
let d: Duration = Duration::from_secs(90);
println!(d.to_string()); // "1m 30s"
let sw: Stopwatch = Stopwatch::start();
// ... do work ...
let elapsed: Duration = sw.elapsed();
println!("took", elapsed.to_string());
return 0;
}
Duration::from_millis / from_secs / from_minutes / from_hours build durations; .add / .sub combine two durations. A Stopwatch is the clean way to measure elapsed time — Stopwatch::start() then sw.elapsed(). (Recall from the concurrency chapter that after(d) turns a Duration into a timeout channel.)
Files and the environment
stdlib::fs reads and writes files; stdlib::env reaches the process environment.
import stdlib::fs::*;
import stdlib::env::*;
fn main() -> i32 {
if fs_exists("config.txt") {
let text: string = fs_read("config.txt");
let lines: *Vector<string> = fs_read_lines("config.txt");
println!("config has", lines.len(), "lines");
}
fs_write("out.txt", "generated by glide\n");
let home: string = env_get("HOME"); // "" if unset
if env_has("DEBUG") { println!("debug mode"); }
return 0;
}
The fs_* functions are deliberately flat: fs_read, fs_write, fs_exists, fs_read_lines, fs_list(dir, suffix), fs_mkdir_p, fs_remove_file, and friends. fs_read_or_default(path, fallback) is the one-liner for "read this, or use a default if it's missing."
JSON
stdlib::json parses and builds JSON through one type, *JsonValue. Reading is the common case:
import stdlib::json::*;
fn main() -> i32 {
let doc: *JsonValue = JsonValue::parse("{\"name\":\"alice\",\"age\":30}");
// typed getters return !T — handle the missing/wrong-type case:
let name: !string = doc.get_string("name");
if name.ok { println!("name:", name.val); } // alice
let age: !i32 = doc.get_int("age");
if age.ok { println!("age:", age.val); } // 30
return 0;
}
Building JSON goes the other way — construct values and emit() them to text:
import stdlib::json::*;
fn main() -> i32 {
let obj: *JsonValue = JsonValue::object();
obj.obj_set("id", JsonValue::int(7));
obj.obj_set("ok", JsonValue::bool(true));
println!(obj.emit()); // {"id":7,"ok":true}
return 0;
}
The rest of the library, chapter by chapter
This tour skimmed the surface. The chapters that follow are the deep reference — every public function, with worked examples — one chapter per module:
- Prelude — what's in scope with no import (
println!,format!, the!T/?Tmachinery) - Strings · Vectors · Collections (
HashMap,HashSet,Pair) · Iterators - Math · Time
- Files & I/O · OS · Environment · Process
- JSON · Regex · Random · Encoding & hashing (base64, hex, crypto, compress)
- Logging · Sync primitives · CLI / argparse · Networking · Mail · System
Networking culminates in Building an HTTP server; testing lives in Testing and benchmarks.
Recap
Where to next
You've seen the shape of the library. The next chapter — Prelude — starts the module-by-module reference with what's always in scope, and the chapters after it work through each stdlib:: module in turn.