All of rusts persistent immutable datastructure libraries like im make use of this for drastically more efficient operations without loss in capability or programming style.
I used the same principle for my rust re-imagination of datascript [1], and the borrow checker together with some merkle dag magic allows for some really interesting optimisations, like set operations with almost no additional overhead.
Which allows me to do stuff like not have insert be the primary way you get data into a database, you simply create database fragments and union them:
let herbert = ufoid();
let dune = ufoid();
let mut library = TribleSet::new();
library += entity! { &herbert @
literature::firstname: "Frank",
literature::lastname: "Herbert",
};
library += entity! { &dune @
literature::title: "Dune",
literature::author: &herbert,
literature::quote: ws.put(
"I must not fear. Fear is the mind-killer."
),
};
ws.commit(library, "import dune");
The entity! macro itself just creates a TribleSet and += is just union.In Clojure this would have been too expensive because you would have to make a copy of the tries every time, and not be able to reuse the trie nodes due to borrow checking their unique ownership.
And thank you for highlighting the conceptual link to Rust's borrow checker. Clojure and Rust are far and away my two favorite languages and this largely articulates why: they both have language-level constructs to completely solve the data ownership problem. Not just "here's some tools to optionally solve it, good luck" but truly, fully solve it. Full stop.
Almost every other language leaves ownership enforcement up to the developer. Clojure and Rust take entirely different approaches to virtually everything, but they converge on this one point and it's a crucial one. Types, syntax, compilation models, garbage collection, etc. are all secondary concerns to managed data ownership IMO.
I semi-ported it to c# here: https://github.com/bjoli/RrbList/tree/main/src/Collections
It is faster than clojures vectors (running on the JVM, so apples and cucumbers) in all cases, and mostly beats scala's vectors except for splitting which is crazy fast in scala's vectors).
https://github.com/nickik/RRB-Vector-in-Dylan/blob/master/RR...
Just pre-allocating leaf nodes can reduce iteration overhead by 40%.
I have always thought Hickeys main contribution was making it default in a coherent way, and proved it could be done. Before clojure most peoplle still thought immutable data structures were too I practical.
Scala got introduced in 2004, with the first Programming in Scala book, in 2008.
HN had plenty of PureScript and Elm.
FP finally was going to get their spotlight, and then mainstream languages got enough FP features to keep being the go to tooling.
I still don’t understand why they’re referred to as persistent vectors rather than immutable vectors, but I digress.
I believe that immutable just means, well, immutable, but persistent means that updates are achieved via structural sharing, so they’re efficient.
if you think immutable updates are O(n) in 2026, you're so far behind the curve it's laughable
it's crazy how many ppl i interview just stop thinking and insist you can't do better than O(n)
You wanted 2+1 to yield 3, but instead you get a runtime exception telling you that 2 can't be changed.
haskell too had them (IntMap honestly works fine in that use case)