- types.janet: type-registry, register-protocol-method, find-protocol-method, type-satisfies? - core.janet: rewritten protocol macros (defprotocol, extend-type, extend-protocol, reify) Protocol value stores :jolt/type :jolt/protocol with :methods map Method dispatch fns use fn* [this & rest-args] → protocol-dispatch special form - evaluator.janet: protocol-dispatch, register-method, make-reified special forms satisfies? special form with type registry lookup special-symbol? entries for all 3 protocol ops + satisfies? - 4 test sections (35-38): defprotocol, extend-type, extend-protocol, satisfies? extend-type: basic dispatch works (42 constant), .-field accessor needs further debug satisfies?: fully functional with type registry - 315 ok, 2 fail (pre-existing, unchanged)
2.6 KiB
2.6 KiB
| name | description |
|---|---|
| jolt-persistent-structures | PersistentHashMap, PersistentHashSet, and LazySeq implementation patterns in Janet tables |
jolt-persistent-structures
PersistentHashMap, PersistentHashSet, and LazySeq implementation patterns in Janet tables.
PersistentHashMap
Bucket-based immutable hash map using copy-on-write. Stores data in :buckets (array of flat [k v k v ...] bucket arrays), :cnt (entry count), :jolt/deftype type tag, and :_meta.
Core functions (in phm.janet)
make-phm [& kvs]— create from key-value pairsphm-get [m k &opt default]— lookup with optional defaultphm-assoc [m k v]— return new map with k→vphm-dissoc [m k]— return new map without kphm-contains? [m k]— membership checkphm-count [m]— number of entriesphm-to-struct [m]— convert to Janet struct (for equality, keys, vals)phm-entries [m]— return[[k v] ...]pairs
Core function integration (core.janet)
Each core fn checks phm? first, then falls through to struct/table logic:
core-get→phm-getcore-assoc→phm-assoccore-dissoc→phm-dissoccore-contains?→phm-contains?core-count→phm-countcore-keys/vals/seq→ viaphm-to-structcore-merge/merge-with→ PHM-aware iterationcore-empty?→ check:cnt = 0core-conj→phm-assocfor[k v]pairs
Gotchas
core-map?:(if (and (table? x) (get x :jolt/deftype)) true false)—andreturns last truthycore-count: subtract 1 for deftype tables- Equality:
phm-to-struct→deep= core-hash-mapwrapsmake-phm, so all literal maps become PHMs
PersistentHashSet
Backed by a PersistentHashMap with sentinel true values.
Core functions (in phm.janet)
make-phs [& xs]— create from itemsphs-conj [s & xs]— add items (idempotent)phs-disj [s & xs]— remove itemsphs-contains? [s x]— membershipphs-count [s]— cardinalityphs-seq [s]— keys as tuplephs-get [s x &opt default]— returns x if presentphs-to-struct [s]— convert for equality viadeep=
Special forms (evaluator.janet)
:jolt/sethandler:(apply make-phs (form :value))"disj"dispatch — validates set?, callsphs-disj"set?"dispatch — callsset?predicate
LazySeq
Realize-once thunk wrapper.
Core functions (in phm.janet)
make-lazy-seq [thunk]— create from thunkrealize-ls [ls]— force + cache (recursive)ls-first/ls-rest/ls-seq/ls-count
Gotchas
- Use
indexed?nottuple?for realized sequences - Avoid
val'(parse error), usevf