Trie-based Persistent Vector for O(log n) Random Access
Tutorial
The Problem
Purely functional data structures must never mutate in place — every update produces a new version while preserving the old one. Naive approaches copy the entire structure on each update, giving O(n) time. A trie-based persistent vector solves this by sharing unchanged subtrees between versions, achieving O(log n) reads and writes while remaining fully immutable. This structure underpins Clojure's persistent vector and any system requiring cheap snapshots or time-travel debugging.
🎯 Learning Outcomes
Arc in Rust enables safe structural sharing without a garbage collectorCode Example
#![allow(clippy::all)]
// placeholderKey Differences
Arc<T> with explicit reference counting and no GC pauses.Arc wrapping to opt into sharing.Arc has atomic overhead on clone/drop; OCaml's GC has periodic pause overhead — different latency trade-offs.Box or Arc to break recursive type size cycles.OCaml Approach
OCaml's garbage collector handles structural sharing automatically — the GC keeps shared nodes alive as long as any version references them. Persistent vectors are typically implemented as trees of arrays (type 'a t = Leaf of 'a array | Node of 'a t array). Because OCaml values are immutable by default, sharing is the natural result of returning old sub-nodes without copying.
Full Source
#![allow(clippy::all)]
// placeholderDeep Comparison
<!-- Comparison will be generated by Claude Code -->
Exercises
get(index) on a simple binary trie (branching factor 2) and verify O(log n) node visits with a counter.set(index, value) returning a new root, sharing all unchanged subtrees via Arc::clone.push_back that grows the trie by one level when the current depth is exhausted.