Collections
Toka provides a rich set of data structures for storing and organizing data efficiently.
Vec (Dynamic Array)
import std/io::println
import std/vec::Vec
fn example() {
auto numbers# = Vec<i32>::new()
numbers#.push(1)
numbers#.push(2)
numbers#.push(3)
println("{}", numbers.at(0)) // 1
auto i# = 0:usize
loop i < numbers.len() {
println("{}", numbers.at(i))
i = i + 1:usize
}
}
Map (Hash Map)
import std/io::println
import std/hashmap::HashMap
import core/option::Option
import core/primitives
fn example() {
auto scores# = HashMap<i32, i32>::new()
scores#.insert(1, 95)
scores#.insert(2, 87)
match scores.get(1) {
auto Option<i32>::Some(score) => { println("ID 1: {}", score) }
auto Option<i32>::None => { println("Not found") }
}
}
BTreeMap (Ordered Map)
import std/io::println
import std/btreemap::BTreeMap
import core/primitives
fn example() {
auto items# = BTreeMap<str, i32>::new()
items#.insert("apple", 5)
items#.insert("banana", 3)
items#.insert("cherry", 8)
println("Iterated")
}
BTreeSet (Ordered Set)
import std/io::println
import std/btreeset::BTreeSet
import core/primitives
fn example() {
auto unique# = BTreeSet<i32>::new()
unique#.insert(3)
unique#.insert(1)
unique#.insert(2)
unique#.insert(1) // Duplicate, ignored
println("{}", unique.len())
}
Deque (Double-Ended Queue)
import std/io::println
import std/deque::VecDeque
fn example() {
auto queue# = VecDeque<str>::new()
queue#.push_back("first")
queue#.push_back("second")
queue#.push_front("priority")
queue#.pop_front()
println("{}", queue.len())
}
Slab (Generational Slab Allocator)
Toka completely abolishes linked lists to embrace the contiguous physical memory topology of modern CPUs. Instead, the standard library introduces the generational slab allocator std/slab::Slab. It manages objects as slots inside a contiguous memory buffer (Vec), supporting rapid $O(1)$ insertion, removal, and retrieval. It employs a SlabID generational check technique to fully eliminate the risk of ABA problems or stale index lookups.
The Slab's lookup methods (get and get_mut) implement advanced lifetime dependency declarations (<- self), returning zero-copy Option<&'T> and Option<&#'T> borrows.
import std/slab::{Slab, SlabID}
import std/io::{println}
import core/option::{Option}
shape Entity (
name: string,
val: i32
)
fn main() -> i32 {
auto slab# = Slab<Entity>::new()
// 1. Insert elements, returning a SlabID containing both index and generation
auto id1 = slab#.insert(Entity(name = string::from("alpha"), val = 10))
auto id2 = slab#.insert(Entity(name = string::from("beta"), val = 20))
// 2. Retrieve zero-copy borrowed views safely
auto e1_opt = slab.get(id1.clone())
if e1_opt.is_some() {
auto &e1 = e1_opt.unwrap()
println("ID1 val: {}", e1.val as i64) // 10
}
// 3. Remove an element and reclaim its slot
auto removed = slab#.remove(id1.clone())
// 4. Insert another element: Slab automatically reuses Slot 0!
// However, the generation counter automatically increments to 2!
auto id3 = slab#.insert(Entity(name = string::from("gamma"), val = 30))
// 5. Querying with the stale id1 now safely returns None, preventing ABA reads!
auto old_opt = slab.get(id1)
assert(old_opt.is_none(), "generational ID should prevent ABA stale read")
return 0
}
Heap (Priority Queue)
import std/io::println
import std/heap::BinaryHeap
import core/primitives
fn example() {
auto max_cmp: fn(i32, i32) -> bool = { a, b => a > b }
auto heap# = BinaryHeap<i32>::new(max_cmp)
heap#.push(5)
heap#.push(10)
heap#.push(3)
heap#.pop()
println("10")
}
Set
import std/io::println
import std/hashset::HashSet
import core/primitives
fn example() {
auto tags# = HashSet<i32>::new()
tags#.insert(1)
tags#.insert(2)
tags#.insert(3)
if tags.contains(2) {
println("Found 2!")
}
}