Skip to content

feat: use sorted collections for sorted accumulators - #24

Open
hiredman wants to merge 2 commits into
mainfrom
use-sorted-bags-for-accumulators
Open

hiredman wants to merge 2 commits into
mainfrom
use-sorted-bags-for-accumulators

Conversation

@hiredman

@hiredman hiredman commented Sep 30, 2026 •

Copy link
Copy Markdown

sorting-by and sorted-grouping-by sorted their facts again on every conversion. Clojure sorted collections cannot hold that state, because they carry a comparator, and a comparator does not serialize.

Change

  • clara.rules.accumulators.wb-tree: a sorted bag and a sorted map on a weight-balanced tree (Adams, with the (3, 2) parameters of Hirai and Yamamoto). Every operation is O(log n) in the worst case, and a merge is a split-and-join union.
  • No comparator inside. The collections hold no comparator. Each operation that compares takes one as an argument, so the state is plain data.
  • The bag keeps every item verbatim, and remove-item removes the newest item that is =.
  • sorted-map-view puts a Clojure sorted map over a map and its comparator.
  • sorting-by keeps a bag. sorted-grouping-by keeps a map of bags and returns a view.
  • Fressian: handlers for the bag and the map. The view is written as a plain map.
  • Reader tags: #clara.rules/sorted-bag and #clara.rules/sorted-map.

Behaviour changes

  • sorting-by returns a vector. It used to return the ArraySeq that sort-by gives.
  • sorted-grouping-by returns a sorted map with vector groups. The old array-map result lost its order with nine or more groups.

Review notes

  • Nothing detects a comparator that differs from the one that built the collection.
  • bag-vec opens the package-private PersistentVector constructor by reflection, with a fallback. It is about 1.5 times faster than a transient reduce.

Tests

New tests for the tree, Fressian and session durability. make test passes: 1,003 tests, 0 failures.

Kevin Downey added 2 commits September 30, 2026 15:35
gb trees are not great as a persistent data structure because it only
has amortized time guarantees, which don't work as well when you can
keep old versions data structures around.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant