feat: persistent singly-linked lists with O(1) conj/cons prepend
Round 3 of the persistent-collections work. Lists were immutable Janet arrays, so conj/cons-prepend was an O(n) copy (O(n^2) to build a list) — a large perf gap vs Clojure's PersistentList. Add src/jolt/plist.janet: an immutable cons-cell list (first/rest/count), same algorithm as Clojure/CLJS/jank PersistentList. conj/cons onto a list now creates an O(1) node that shares the existing list as its tail (no copy), with a cached O(1) count. Repeated conj is O(n) total instead of O(n^2). Hooked plist through first/rest/next/seq/count/peek/pop/nth/empty/empty?, the predicates (list?/seq?/coll?/sequential?), realize-for-iteration, =, coll->cells (concat/lazy), both printers, destructuring, and instance? tags. (list ...) and quoted lists stay arrays; only conj/cons introduce plist nodes, so the surface and risk stay small. Verified: reduce-conj of 200k elements runs in ~0.4s (was effectively O(n^2)). conformance 206/206, features 78/78 (+7 list regressions), jank 120 (+1).
This commit is contained in:
parent
e43f39bc36
commit
a0c9696900
9 changed files with 142 additions and 22 deletions
|
|
@ -5,6 +5,7 @@
|
|||
(use ./types)
|
||||
(use ./phm)
|
||||
(use ./pv)
|
||||
(use ./plist)
|
||||
(use ./config)
|
||||
(use ./reader)
|
||||
|
||||
|
|
@ -36,6 +37,17 @@
|
|||
(++ i)))
|
||||
(push-str buf "]"))
|
||||
|
||||
(plist? v)
|
||||
(do
|
||||
(push-str buf "(")
|
||||
(let [a (pl->array v) n (length a)]
|
||||
(var i 0)
|
||||
(while (< i n)
|
||||
(write-value (in a i) buf)
|
||||
(when (< (+ i 1) n) (push-str buf " "))
|
||||
(++ i)))
|
||||
(push-str buf ")"))
|
||||
|
||||
(tuple? v)
|
||||
(do
|
||||
(push-str buf "[")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue