From 04232e0ebe404fd6bc461f4c47ade4eb9b485305 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Thu, 4 Jun 2020 15:22:05 -0400 Subject: [PATCH 1/8] zuse: add subset arm to ordered-map --- pkg/arvo/sys/zuse.hoon | 54 +++++++++++++++++++++++ pkg/arvo/tests/sys/zuse/ordered-map.hoon | 56 +++++++++++++++++++++--- 2 files changed, 105 insertions(+), 5 deletions(-) diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 57091eb50..1536604fb 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -7317,6 +7317,60 @@ ?: (compare key.n.a key.n.b) $(l.b $(b l.b, r.a ~), a r.a) $(r.b $(b r.b, l.a ~), a l.a) + :: + :: +subset: take a range excluding start and/or end and all elements + :: outside the range + :: + ++ subset + |= $: tre=(tree item) + start=(unit key) + end=(unit key) + == + ^- (tree item) + |^ + ?: ?&(?=(~ start) ?=(~ end)) + tre + ?~ start + (del-span tre %end end) + ?~ end + (del-span tre %start start) + ?> (lth u.start u.end) + =. tre (del-span tre %start start) + (del-span tre %end end) + :: + ++ del-span + |= [a=(tree item) b=?(%start %end) c=(unit key)] + ^- (tree item) + ?~ a a + ?~ c a + ?- b + %start + :: found key + ?: =(key.n.a u.c) + (nip a(l ~)) + :: traverse to find key + ?: (compare key.n.a u.c) + :: found key to the left of start + (del-span (nip a(l ~)) b c) + :: found key to the right of start + =/ lef $(a l.a) + =. l.a lef + a + :: + %end + :: found key + ?: =(u.c key.n.a) + (nip a(r ~)) + :: traverse to find key + ?: (compare key.n.a u.c) + :: found key to the left of end + =/ rig $(a r.a) + =. r.a rig + a + :: found key to the right of end + (del-span (nip a(r ~)) b c) + == + -- -- :: :: :::: ++userlib :: (2u) non-vane utils diff --git a/pkg/arvo/tests/sys/zuse/ordered-map.hoon b/pkg/arvo/tests/sys/zuse/ordered-map.hoon index 7764dc05b..ad9f24a90 100644 --- a/pkg/arvo/tests/sys/zuse/ordered-map.hoon +++ b/pkg/arvo/tests/sys/zuse/ordered-map.hoon @@ -1,8 +1,4 @@ -:: TODO: move +ordered-map to zuse -:: /+ *test -/= ames /sys/vane/ames -:: =/ items-from-keys |= keys=(list @ud) %+ turn keys @@ -12,7 +8,7 @@ =/ test-items=(list [@ud @tas]) (items-from-keys (gulf 0 6)) :: -=/ atom-map ((ordered-map:ames @ud @tas) lte) +=/ atom-map ((ordered-map @ud @tas) lte) :: |% ++ test-ordered-map-gas ^- tang @@ -57,6 +53,56 @@ !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f]]) !> b :: +++ test-ordered-map-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a `0 `4) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[1^%b] [2^%c] [3^%d]]) + !> b +:: +++ test-ordered-map-null-start-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a ~ `5) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e]]) + !> b +:: +++ test-ordered-map-null-end-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a `1 ~) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) + !> b +:: +++ test-ordered-map-double-null-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a ~ ~) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) + !> b +:: +++ test-ordered-map-not-found-start-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ ~[[1^%b]]) + :: + =/ b (subset:atom-map a `0 ~) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[1^%b]]) + !> b +:: ++ test-ordered-map-traverse ^- tang :: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) From 4168344c3b2fd7f26271c11dbb20f16a46405c8b Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Thu, 4 Jun 2020 16:38:18 -0400 Subject: [PATCH 2/8] zuse: added mop, a mold builder for ordered-maps --- pkg/arvo/sys/zuse.hoon | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 1536604fb..3e2bf905c 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -7070,6 +7070,15 @@ $(pops [oldest pops]) -- -- +:: +++ mop + |* [key=mold value=mold] + |= ord=$-([key key] ?) + |= a=* + =/ b ;;((tree [key=key val=value]) a) + ?> (check-balance:((ordered-map key value) ord) b) + b +:: :: $mk-item: constructor for +ordered-map item type :: ++ mk-item |$ [key val] [key=key val=val] From cd5840770e08fcaadeba2e723870cdc3d7520ba2 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Thu, 4 Jun 2020 17:51:05 -0400 Subject: [PATCH 3/8] zuse: ordered-map subset style fixes --- pkg/arvo/sys/zuse.hoon | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 3e2bf905c..61a9a1b6b 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -7360,11 +7360,9 @@ :: traverse to find key ?: (compare key.n.a u.c) :: found key to the left of start - (del-span (nip a(l ~)) b c) + $(a (nip a(l ~))) :: found key to the right of start - =/ lef $(a l.a) - =. l.a lef - a + a(l $(a l.a)) :: %end :: found key @@ -7373,11 +7371,9 @@ :: traverse to find key ?: (compare key.n.a u.c) :: found key to the left of end - =/ rig $(a r.a) - =. r.a rig - a + a(r $(a r.a)) :: found key to the right of end - (del-span (nip a(r ~)) b c) + $(a (nip a(r ~))) == -- -- From 7cdc12ff4c01a5e7a2ce24ff23b61f48f6b2303c Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Thu, 4 Jun 2020 17:51:15 -0400 Subject: [PATCH 4/8] lib: or-map test library --- pkg/arvo/lib/or-map.hoon | 301 +++++++++++++++++++++++ pkg/arvo/tests/lib/or-map.hoon | 143 +++++++++++ pkg/arvo/tests/sys/zuse/ordered-map.hoon | 98 ++++---- 3 files changed, 493 insertions(+), 49 deletions(-) create mode 100644 pkg/arvo/lib/or-map.hoon create mode 100644 pkg/arvo/tests/lib/or-map.hoon diff --git a/pkg/arvo/lib/or-map.hoon b/pkg/arvo/lib/or-map.hoon new file mode 100644 index 000000000..6c568203e --- /dev/null +++ b/pkg/arvo/lib/or-map.hoon @@ -0,0 +1,301 @@ +|% +:: +:: $mk-item: constructor for +ordered-map item type +:: +++ mk-item |$ [key val] [key=key val=val] +:: +ordered-map: treap with user-specified horizontal order +:: +:: Conceptually smaller items go on the left, so the item with the +:: smallest key can be popped off the head. If $key is `@` and +:: .compare is +lte, then the numerically smallest item is the head. +:: +++ or-map + |* [key=mold val=mold] + => |% + +$ item (mk-item key val) + -- + :: +compare: item comparator for horizontal order + :: + |= compare=$-([key key] ?) + |% + :: +check-balance: verify horizontal and vertical orderings + :: + ++ check-balance + =| [l=(unit key) r=(unit key)] + |= a=(tree item) + ^- ? + :: empty tree is valid + :: + ?~ a %.y + :: nonempty trees must maintain several criteria + :: + ?& :: if .n.a is left of .u.l, assert horizontal comparator + :: + ?~(l %.y (compare key.n.a u.l)) + :: if .n.a is right of .u.r, assert horizontal comparator + :: + ?~(r %.y (compare u.r key.n.a)) + :: if .a is not leftmost element, assert vertical order between + :: .l.a and .n.a and recurse to the left with .n.a as right + :: neighbor + :: + ?~(l.a %.y &((mor key.n.a key.n.l.a) $(a l.a, l `key.n.a))) + :: if .a is not rightmost element, assert vertical order + :: between .r.a and .n.a and recurse to the right with .n.a as + :: left neighbor + :: + ?~(r.a %.y &((mor key.n.a key.n.r.a) $(a r.a, r `key.n.a))) + == + :: +put: ordered item insert + :: + ++ put + |= [a=(tree item) =key =val] + ^- (tree item) + :: base case: replace null with single-item tree + :: + ?~ a [n=[key val] l=~ r=~] + :: base case: overwrite existing .key with new .val + :: + ?: =(key.n.a key) a(val.n val) + :: if item goes on left, recurse left then rebalance vertical order + :: + ?: (compare key key.n.a) + =/ l $(a l.a) + ?> ?=(^ l) + ?: (mor key.n.a key.n.l) + a(l l) + l(r a(l r.l)) + :: item goes on right; recurse right then rebalance vertical order + :: + =/ r $(a r.a) + ?> ?=(^ r) + ?: (mor key.n.a key.n.r) + a(r r) + r(l a(r l.r)) + :: +peek: produce head (smallest item) or null + :: + ++ peek + |= a=(tree item) + ^- (unit item) + :: + ?~ a ~ + ?~ l.a `n.a + $(a l.a) + :: +pop: produce .head (smallest item) and .rest or crash if empty + :: + ++ pop + |= a=(tree item) + ^- [head=item rest=(tree item)] + :: + ?~ a !! + ?~ l.a [n.a r.a] + :: + =/ l $(a l.a) + :- head.l + :: load .rest.l back into .a and rebalance + :: + ?: |(?=(~ rest.l) (mor key.n.a key.n.rest.l)) + a(l rest.l) + rest.l(r a(r r.rest.l)) + :: +del: delete .key from .a if it exists, producing value iff deleted + :: + ++ del + |= [a=(tree item) =key] + ^- [(unit val) (tree item)] + :: + ?~ a [~ ~] + :: we found .key at the root; delete and rebalance + :: + ?: =(key key.n.a) + [`val.n.a (nip a)] + :: recurse left or right to find .key + :: + ?: (compare key key.n.a) + =+ [found lef]=$(a l.a) + [found a(l lef)] + =+ [found rig]=$(a r.a) + [found a(r rig)] + :: +nip: remove root; for internal use + :: + ++ nip + |= a=(tree item) + ^- (tree item) + :: + ?> ?=(^ a) + :: delete .n.a; merge and balance .l.a and .r.a + :: + |- ^- (tree item) + ?~ l.a r.a + ?~ r.a l.a + ?: (mor key.n.l.a key.n.r.a) + l.a(r $(l.a r.l.a)) + r.a(l $(r.a l.r.a)) + :: +traverse: stateful partial inorder traversal + :: + :: Mutates .state on each run of .f. Starts at .start key, or if + :: .start is ~, starts at the head (item with smallest key). Stops + :: when .f produces .stop=%.y. Traverses from smaller to larger + :: keys. Each run of .f can replace an item's value or delete the + :: item. + :: + ++ traverse + |* state=mold + |= $: a=(tree item) + =state + f=$-([state item] [(unit val) ? state]) + == + ^+ [state a] + :: acc: accumulator + :: + :: .stop: set to %.y by .f when done traversing + :: .state: threaded through each run of .f and produced by +abet + :: + =/ acc [stop=`?`%.n state=state] + =< abet =< main + |% + ++ abet [state.acc a] + :: +main: main recursive loop; performs a partial inorder traversal + :: + ++ main + ^+ . + :: stop if empty or we've been told to stop + :: + ?~ a . + ?: stop.acc . + :: inorder traversal: left -> node -> right, until .f sets .stop + :: + => left + ?: stop.acc . + => node + ?: stop.acc . + right + :: +node: run .f on .n.a, updating .a, .state, and .stop + :: + ++ node + ^+ . + :: run .f on node, updating .stop.acc and .state.acc + :: + =^ res acc + ?> ?=(^ a) + (f state.acc n.a) + :: apply update to .a from .f's product + :: + =. a + :: if .f requested node deletion, merge and balance .l.a and .r.a + :: + ?~ res (nip a) + :: we kept the node; replace its .val; order is unchanged + :: + ?> ?=(^ a) + a(val.n u.res) + :: + ..node + :: +left: recurse on left subtree, copying mutant back into .l.a + :: + ++ left + ^+ . + ?~ a . + =/ lef main(a l.a) + lef(a a(l a.lef)) + :: +right: recurse on right subtree, copying mutant back into .r.a + :: + ++ right + ^+ . + ?~ a . + =/ rig main(a r.a) + rig(a a(r a.rig)) + -- + :: +tap: convert to list, smallest to largest + :: + ++ tap + |= a=(tree item) + ^- (list item) + :: + =| b=(list item) + |- ^+ b + ?~ a b + :: + $(a l.a, b [n.a $(a r.a)]) + :: +gas: put a list of items + :: + ++ gas + |= [a=(tree item) b=(list item)] + ^- (tree item) + :: + ?~ b a + $(b t.b, a (put a i.b)) + :: +uni: unify two ordered maps + :: + :: .b takes precedence over .a if keys overlap. + :: + ++ uni + |= [a=(tree item) b=(tree item)] + ^- (tree item) + :: + ?~ b a + ?~ a b + ?: =(key.n.a key.n.b) + :: + [n=n.b l=$(a l.a, b l.b) r=$(a r.a, b r.b)] + :: + ?: (mor key.n.a key.n.b) + :: + ?: (compare key.n.b key.n.a) + $(l.a $(a l.a, r.b ~), b r.b) + $(r.a $(a r.a, l.b ~), b l.b) + :: + ?: (compare key.n.a key.n.b) + $(l.b $(b l.b, r.a ~), a r.a) + $(r.b $(b r.b, l.a ~), a l.a) + :: + :: +subset: take a range excluding start and/or end and all elements + :: outside the range + :: + ++ subset + |= $: tre=(tree item) + start=(unit key) + end=(unit key) + == + ^- (tree item) + |^ + ?: ?&(?=(~ start) ?=(~ end)) + tre + ?~ start + (del-span tre %end end) + ?~ end + (del-span tre %start start) + ?> (lth u.start u.end) + =. tre (del-span tre %start start) + (del-span tre %end end) + :: + ++ del-span + |= [a=(tree item) b=?(%start %end) c=(unit key)] + ^- (tree item) + ?~ a a + ?~ c a + ?- b + %start + :: found key + ?: =(key.n.a u.c) + (nip a(l ~)) + :: traverse to find key + ?: (compare key.n.a u.c) + :: found key to the left of start + $(a (nip a(l ~))) + :: found key to the right of start + a(l $(a l.a)) + :: + %end + :: found key + ?: =(u.c key.n.a) + (nip a(r ~)) + :: traverse to find key + ?: (compare key.n.a u.c) + :: found key to the left of end + a(r $(a r.a)) + :: found key to the right of end + $(a (nip a(r ~))) + == + -- + -- +-- diff --git a/pkg/arvo/tests/lib/or-map.hoon b/pkg/arvo/tests/lib/or-map.hoon new file mode 100644 index 000000000..3be2619b2 --- /dev/null +++ b/pkg/arvo/tests/lib/or-map.hoon @@ -0,0 +1,143 @@ +/+ or-map, *test + +=/ items-from-keys + |= keys=(list @ud) + %+ turn keys + |= k=@ud + [k `@tas`(add k %a)] +:: +=/ test-items=(list [@ud @tas]) + (items-from-keys (gulf 0 6)) +:: +=/ atom-map ((or-map:or-map @ud @tas) lte) +:: +|% +++ test-ordered-map-gas ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + %+ expect-eq + !> %.y + !> (check-balance:atom-map a) +:: +++ test-ordered-map-tap ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + %+ expect-eq + !> test-items + !> (tap:atom-map a) +:: +++ test-ordered-map-pop ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + %+ expect-eq + !> [[0 %a] (gas:atom-map ~ (items-from-keys (gulf 1 6)))] + !> (pop:atom-map a) +:: +++ test-ordered-map-peek ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + %+ expect-eq + !> `[0 %a] + !> (peek:atom-map a) +:: +++ test-ordered-map-nip ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (nip:atom-map a) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f]]) + !> b +:: +++ test-ordered-map-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a `0 `4) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[1^%b] [2^%c] [3^%d]]) + !> b +:: +++ test-ordered-map-null-start-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a ~ `5) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e]]) + !> b +:: +++ test-ordered-map-null-end-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a `1 ~) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) + !> b +:: +++ test-ordered-map-double-null-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a ~ ~) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) + !> b +:: +++ test-ordered-map-not-found-start-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ ~[[1^%b]]) + :: + =/ b (subset:atom-map a `0 ~) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[1^%b]]) + !> b +:: +++ test-ordered-map-traverse ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b %- (traverse:atom-map ,(list [@ud @tas])) + :* a + state=~ + :: + |= [s=(list [@ud @tas]) k=@ud v=@tas] + :+ ?: =(3 k) + ~ + [~ `@tas`+(v)] + =(5 k) + [[k v] s] + == + :: + ;: weld + %+ expect-eq + !> (gas:atom-map ~ ~[[0^%b] [1^%c] [2^%d] [4^%f] [5^%g] [6^%g]]) + !> +.b + :: + %+ expect-eq + !> (flop (items-from-keys (gulf 0 5))) + !> -.b + == +:: +++ test-ordered-map-uni ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ (scag 4 test-items)) + =/ b=(tree [@ud @tas]) (gas:atom-map ~ (slag 4 test-items)) + :: + =/ c (uni:atom-map a b) + :: + %+ expect-eq + !> (gas:atom-map ~ test-items) + !> c +-- diff --git a/pkg/arvo/tests/sys/zuse/ordered-map.hoon b/pkg/arvo/tests/sys/zuse/ordered-map.hoon index ad9f24a90..f1ae62d5f 100644 --- a/pkg/arvo/tests/sys/zuse/ordered-map.hoon +++ b/pkg/arvo/tests/sys/zuse/ordered-map.hoon @@ -53,55 +53,55 @@ !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f]]) !> b :: -++ test-ordered-map-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b (subset:atom-map a `0 `4) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[1^%b] [2^%c] [3^%d]]) - !> b -:: -++ test-ordered-map-null-start-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b (subset:atom-map a ~ `5) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e]]) - !> b -:: -++ test-ordered-map-null-end-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b (subset:atom-map a `1 ~) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) - !> b -:: -++ test-ordered-map-double-null-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b (subset:atom-map a ~ ~) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) - !> b -:: -++ test-ordered-map-not-found-start-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ ~[[1^%b]]) - :: - =/ b (subset:atom-map a `0 ~) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[1^%b]]) - !> b +::++ test-ordered-map-subset ^- tang +:: :: +:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) +:: :: +:: =/ b (subset:atom-map a `0 `4) +:: :: +:: %+ expect-eq +:: !> (gas:atom-map ~ ~[[1^%b] [2^%c] [3^%d]]) +:: !> b +:::: +::++ test-ordered-map-null-start-subset ^- tang +:: :: +:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) +:: :: +:: =/ b (subset:atom-map a ~ `5) +:: :: +:: %+ expect-eq +:: !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e]]) +:: !> b +:::: +::++ test-ordered-map-null-end-subset ^- tang +:: :: +:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) +:: :: +:: =/ b (subset:atom-map a `1 ~) +:: :: +:: %+ expect-eq +:: !> (gas:atom-map ~ ~[[2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) +:: !> b +:::: +::++ test-ordered-map-double-null-subset ^- tang +:: :: +:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) +:: :: +:: =/ b (subset:atom-map a ~ ~) +:: :: +:: %+ expect-eq +:: !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) +:: !> b +:::: +::++ test-ordered-map-not-found-start-subset ^- tang +:: :: +:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ ~[[1^%b]]) +:: :: +:: =/ b (subset:atom-map a `0 ~) +:: :: +:: %+ expect-eq +:: !> (gas:atom-map ~ ~[[1^%b]]) +:: !> b :: ++ test-ordered-map-traverse ^- tang :: From d272da0f5769b78247be2a682b0a13d7d712c53a Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Fri, 5 Jun 2020 15:29:40 -0400 Subject: [PATCH 5/8] or-map: added get function based off of +find-ducts in behn --- pkg/arvo/lib/or-map.hoon | 12 ++++++++++++ pkg/arvo/tests/lib/or-map.hoon | 18 +++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/pkg/arvo/lib/or-map.hoon b/pkg/arvo/lib/or-map.hoon index 6c568203e..b918c755e 100644 --- a/pkg/arvo/lib/or-map.hoon +++ b/pkg/arvo/lib/or-map.hoon @@ -248,6 +248,18 @@ $(l.b $(b l.b, r.a ~), a r.a) $(r.b $(b r.b, l.a ~), a l.a) :: + :: +get: get val at key or return ~ + :: + ++ get + |= [a=(tree item) b=key] + ^- (unit val) + ?~ a ~ + ?: =(b key.n.a) + `val.n.a + ?: (ord b key.n.a) + $(a l.a) + $(a r.a) + :: :: +subset: take a range excluding start and/or end and all elements :: outside the range :: diff --git a/pkg/arvo/tests/lib/or-map.hoon b/pkg/arvo/tests/lib/or-map.hoon index 3be2619b2..0f31a6637 100644 --- a/pkg/arvo/tests/lib/or-map.hoon +++ b/pkg/arvo/tests/lib/or-map.hoon @@ -1,5 +1,5 @@ /+ or-map, *test - +:: =/ items-from-keys |= keys=(list @ud) %+ turn keys @@ -28,6 +28,22 @@ !> test-items !> (tap:atom-map a) :: +++ test-ordered-map-get ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + %+ expect-eq + !> [~ [0^%a]] + !> (get:atom-map a 0) +:: +++ test-ordered-map-sig-get ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + %+ expect-eq + !> ~ + !> (get:atom-map a 7) +:: ++ test-ordered-map-pop ^- tang :: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) From 24e0d597ba782a31d644ed2c255a27f00dbdc024 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Fri, 5 Jun 2020 15:49:53 -0400 Subject: [PATCH 6/8] or-map: added get arm and tested it --- pkg/arvo/lib/or-map.hoon | 2 +- pkg/arvo/tests/lib/or-map.hoon | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/arvo/lib/or-map.hoon b/pkg/arvo/lib/or-map.hoon index b918c755e..060b0f631 100644 --- a/pkg/arvo/lib/or-map.hoon +++ b/pkg/arvo/lib/or-map.hoon @@ -256,7 +256,7 @@ ?~ a ~ ?: =(b key.n.a) `val.n.a - ?: (ord b key.n.a) + ?: (compare b key.n.a) $(a l.a) $(a r.a) :: diff --git a/pkg/arvo/tests/lib/or-map.hoon b/pkg/arvo/tests/lib/or-map.hoon index 0f31a6637..a6dd5f7f1 100644 --- a/pkg/arvo/tests/lib/or-map.hoon +++ b/pkg/arvo/tests/lib/or-map.hoon @@ -33,8 +33,8 @@ =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) :: %+ expect-eq - !> [~ [0^%a]] - !> (get:atom-map a 0) + !> [~ %d] + !> (get:atom-map a 3) :: ++ test-ordered-map-sig-get ^- tang :: From 64a30fea6290e95c60e07b9737c72c6b6dfe77e7 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Thu, 2 Jul 2020 16:16:22 -0400 Subject: [PATCH 7/8] ordered-map: got %zuse to compile and all tests to pass --- pkg/arvo/lib/or-map.hoon | 313 ----------------------- pkg/arvo/sys/zuse.hoon | 15 +- pkg/arvo/tests/lib/or-map.hoon | 159 ------------ pkg/arvo/tests/sys/zuse/ordered-map.hoon | 98 +++---- 4 files changed, 63 insertions(+), 522 deletions(-) delete mode 100644 pkg/arvo/lib/or-map.hoon delete mode 100644 pkg/arvo/tests/lib/or-map.hoon diff --git a/pkg/arvo/lib/or-map.hoon b/pkg/arvo/lib/or-map.hoon deleted file mode 100644 index 060b0f631..000000000 --- a/pkg/arvo/lib/or-map.hoon +++ /dev/null @@ -1,313 +0,0 @@ -|% -:: -:: $mk-item: constructor for +ordered-map item type -:: -++ mk-item |$ [key val] [key=key val=val] -:: +ordered-map: treap with user-specified horizontal order -:: -:: Conceptually smaller items go on the left, so the item with the -:: smallest key can be popped off the head. If $key is `@` and -:: .compare is +lte, then the numerically smallest item is the head. -:: -++ or-map - |* [key=mold val=mold] - => |% - +$ item (mk-item key val) - -- - :: +compare: item comparator for horizontal order - :: - |= compare=$-([key key] ?) - |% - :: +check-balance: verify horizontal and vertical orderings - :: - ++ check-balance - =| [l=(unit key) r=(unit key)] - |= a=(tree item) - ^- ? - :: empty tree is valid - :: - ?~ a %.y - :: nonempty trees must maintain several criteria - :: - ?& :: if .n.a is left of .u.l, assert horizontal comparator - :: - ?~(l %.y (compare key.n.a u.l)) - :: if .n.a is right of .u.r, assert horizontal comparator - :: - ?~(r %.y (compare u.r key.n.a)) - :: if .a is not leftmost element, assert vertical order between - :: .l.a and .n.a and recurse to the left with .n.a as right - :: neighbor - :: - ?~(l.a %.y &((mor key.n.a key.n.l.a) $(a l.a, l `key.n.a))) - :: if .a is not rightmost element, assert vertical order - :: between .r.a and .n.a and recurse to the right with .n.a as - :: left neighbor - :: - ?~(r.a %.y &((mor key.n.a key.n.r.a) $(a r.a, r `key.n.a))) - == - :: +put: ordered item insert - :: - ++ put - |= [a=(tree item) =key =val] - ^- (tree item) - :: base case: replace null with single-item tree - :: - ?~ a [n=[key val] l=~ r=~] - :: base case: overwrite existing .key with new .val - :: - ?: =(key.n.a key) a(val.n val) - :: if item goes on left, recurse left then rebalance vertical order - :: - ?: (compare key key.n.a) - =/ l $(a l.a) - ?> ?=(^ l) - ?: (mor key.n.a key.n.l) - a(l l) - l(r a(l r.l)) - :: item goes on right; recurse right then rebalance vertical order - :: - =/ r $(a r.a) - ?> ?=(^ r) - ?: (mor key.n.a key.n.r) - a(r r) - r(l a(r l.r)) - :: +peek: produce head (smallest item) or null - :: - ++ peek - |= a=(tree item) - ^- (unit item) - :: - ?~ a ~ - ?~ l.a `n.a - $(a l.a) - :: +pop: produce .head (smallest item) and .rest or crash if empty - :: - ++ pop - |= a=(tree item) - ^- [head=item rest=(tree item)] - :: - ?~ a !! - ?~ l.a [n.a r.a] - :: - =/ l $(a l.a) - :- head.l - :: load .rest.l back into .a and rebalance - :: - ?: |(?=(~ rest.l) (mor key.n.a key.n.rest.l)) - a(l rest.l) - rest.l(r a(r r.rest.l)) - :: +del: delete .key from .a if it exists, producing value iff deleted - :: - ++ del - |= [a=(tree item) =key] - ^- [(unit val) (tree item)] - :: - ?~ a [~ ~] - :: we found .key at the root; delete and rebalance - :: - ?: =(key key.n.a) - [`val.n.a (nip a)] - :: recurse left or right to find .key - :: - ?: (compare key key.n.a) - =+ [found lef]=$(a l.a) - [found a(l lef)] - =+ [found rig]=$(a r.a) - [found a(r rig)] - :: +nip: remove root; for internal use - :: - ++ nip - |= a=(tree item) - ^- (tree item) - :: - ?> ?=(^ a) - :: delete .n.a; merge and balance .l.a and .r.a - :: - |- ^- (tree item) - ?~ l.a r.a - ?~ r.a l.a - ?: (mor key.n.l.a key.n.r.a) - l.a(r $(l.a r.l.a)) - r.a(l $(r.a l.r.a)) - :: +traverse: stateful partial inorder traversal - :: - :: Mutates .state on each run of .f. Starts at .start key, or if - :: .start is ~, starts at the head (item with smallest key). Stops - :: when .f produces .stop=%.y. Traverses from smaller to larger - :: keys. Each run of .f can replace an item's value or delete the - :: item. - :: - ++ traverse - |* state=mold - |= $: a=(tree item) - =state - f=$-([state item] [(unit val) ? state]) - == - ^+ [state a] - :: acc: accumulator - :: - :: .stop: set to %.y by .f when done traversing - :: .state: threaded through each run of .f and produced by +abet - :: - =/ acc [stop=`?`%.n state=state] - =< abet =< main - |% - ++ abet [state.acc a] - :: +main: main recursive loop; performs a partial inorder traversal - :: - ++ main - ^+ . - :: stop if empty or we've been told to stop - :: - ?~ a . - ?: stop.acc . - :: inorder traversal: left -> node -> right, until .f sets .stop - :: - => left - ?: stop.acc . - => node - ?: stop.acc . - right - :: +node: run .f on .n.a, updating .a, .state, and .stop - :: - ++ node - ^+ . - :: run .f on node, updating .stop.acc and .state.acc - :: - =^ res acc - ?> ?=(^ a) - (f state.acc n.a) - :: apply update to .a from .f's product - :: - =. a - :: if .f requested node deletion, merge and balance .l.a and .r.a - :: - ?~ res (nip a) - :: we kept the node; replace its .val; order is unchanged - :: - ?> ?=(^ a) - a(val.n u.res) - :: - ..node - :: +left: recurse on left subtree, copying mutant back into .l.a - :: - ++ left - ^+ . - ?~ a . - =/ lef main(a l.a) - lef(a a(l a.lef)) - :: +right: recurse on right subtree, copying mutant back into .r.a - :: - ++ right - ^+ . - ?~ a . - =/ rig main(a r.a) - rig(a a(r a.rig)) - -- - :: +tap: convert to list, smallest to largest - :: - ++ tap - |= a=(tree item) - ^- (list item) - :: - =| b=(list item) - |- ^+ b - ?~ a b - :: - $(a l.a, b [n.a $(a r.a)]) - :: +gas: put a list of items - :: - ++ gas - |= [a=(tree item) b=(list item)] - ^- (tree item) - :: - ?~ b a - $(b t.b, a (put a i.b)) - :: +uni: unify two ordered maps - :: - :: .b takes precedence over .a if keys overlap. - :: - ++ uni - |= [a=(tree item) b=(tree item)] - ^- (tree item) - :: - ?~ b a - ?~ a b - ?: =(key.n.a key.n.b) - :: - [n=n.b l=$(a l.a, b l.b) r=$(a r.a, b r.b)] - :: - ?: (mor key.n.a key.n.b) - :: - ?: (compare key.n.b key.n.a) - $(l.a $(a l.a, r.b ~), b r.b) - $(r.a $(a r.a, l.b ~), b l.b) - :: - ?: (compare key.n.a key.n.b) - $(l.b $(b l.b, r.a ~), a r.a) - $(r.b $(b r.b, l.a ~), a l.a) - :: - :: +get: get val at key or return ~ - :: - ++ get - |= [a=(tree item) b=key] - ^- (unit val) - ?~ a ~ - ?: =(b key.n.a) - `val.n.a - ?: (compare b key.n.a) - $(a l.a) - $(a r.a) - :: - :: +subset: take a range excluding start and/or end and all elements - :: outside the range - :: - ++ subset - |= $: tre=(tree item) - start=(unit key) - end=(unit key) - == - ^- (tree item) - |^ - ?: ?&(?=(~ start) ?=(~ end)) - tre - ?~ start - (del-span tre %end end) - ?~ end - (del-span tre %start start) - ?> (lth u.start u.end) - =. tre (del-span tre %start start) - (del-span tre %end end) - :: - ++ del-span - |= [a=(tree item) b=?(%start %end) c=(unit key)] - ^- (tree item) - ?~ a a - ?~ c a - ?- b - %start - :: found key - ?: =(key.n.a u.c) - (nip a(l ~)) - :: traverse to find key - ?: (compare key.n.a u.c) - :: found key to the left of start - $(a (nip a(l ~))) - :: found key to the right of start - a(l $(a l.a)) - :: - %end - :: found key - ?: =(u.c key.n.a) - (nip a(r ~)) - :: traverse to find key - ?: (compare key.n.a u.c) - :: found key to the left of end - a(r $(a r.a)) - :: found key to the right of end - $(a (nip a(r ~))) - == - -- - -- --- diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 61a9a1b6b..5dcdece72 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -7160,6 +7160,7 @@ ?~ a ~ ?~ l.a `n.a $(a l.a) + :: :: +pop: produce .head (smallest item) and .rest or crash if empty :: ++ pop @@ -7327,6 +7328,18 @@ $(l.b $(b l.b, r.a ~), a r.a) $(r.b $(b r.b, l.a ~), a l.a) :: + :: +get: get val at key or return ~ + :: + ++ get + |= [a=(tree item) b=key] + ^- (unit val) + ?~ a ~ + ?: =(b key.n.a) + `val.n.a + ?: (compare b key.n.a) + $(a l.a) + $(a r.a) + :: :: +subset: take a range excluding start and/or end and all elements :: outside the range :: @@ -7343,7 +7356,7 @@ (del-span tre %end end) ?~ end (del-span tre %start start) - ?> (lth u.start u.end) + ?> (compare u.start u.end) =. tre (del-span tre %start start) (del-span tre %end end) :: diff --git a/pkg/arvo/tests/lib/or-map.hoon b/pkg/arvo/tests/lib/or-map.hoon deleted file mode 100644 index a6dd5f7f1..000000000 --- a/pkg/arvo/tests/lib/or-map.hoon +++ /dev/null @@ -1,159 +0,0 @@ -/+ or-map, *test -:: -=/ items-from-keys - |= keys=(list @ud) - %+ turn keys - |= k=@ud - [k `@tas`(add k %a)] -:: -=/ test-items=(list [@ud @tas]) - (items-from-keys (gulf 0 6)) -:: -=/ atom-map ((or-map:or-map @ud @tas) lte) -:: -|% -++ test-ordered-map-gas ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - %+ expect-eq - !> %.y - !> (check-balance:atom-map a) -:: -++ test-ordered-map-tap ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - %+ expect-eq - !> test-items - !> (tap:atom-map a) -:: -++ test-ordered-map-get ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - %+ expect-eq - !> [~ %d] - !> (get:atom-map a 3) -:: -++ test-ordered-map-sig-get ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - %+ expect-eq - !> ~ - !> (get:atom-map a 7) -:: -++ test-ordered-map-pop ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - %+ expect-eq - !> [[0 %a] (gas:atom-map ~ (items-from-keys (gulf 1 6)))] - !> (pop:atom-map a) -:: -++ test-ordered-map-peek ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - %+ expect-eq - !> `[0 %a] - !> (peek:atom-map a) -:: -++ test-ordered-map-nip ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b (nip:atom-map a) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f]]) - !> b -:: -++ test-ordered-map-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b (subset:atom-map a `0 `4) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[1^%b] [2^%c] [3^%d]]) - !> b -:: -++ test-ordered-map-null-start-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b (subset:atom-map a ~ `5) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e]]) - !> b -:: -++ test-ordered-map-null-end-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b (subset:atom-map a `1 ~) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) - !> b -:: -++ test-ordered-map-double-null-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b (subset:atom-map a ~ ~) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) - !> b -:: -++ test-ordered-map-not-found-start-subset ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ ~[[1^%b]]) - :: - =/ b (subset:atom-map a `0 ~) - :: - %+ expect-eq - !> (gas:atom-map ~ ~[[1^%b]]) - !> b -:: -++ test-ordered-map-traverse ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) - :: - =/ b %- (traverse:atom-map ,(list [@ud @tas])) - :* a - state=~ - :: - |= [s=(list [@ud @tas]) k=@ud v=@tas] - :+ ?: =(3 k) - ~ - [~ `@tas`+(v)] - =(5 k) - [[k v] s] - == - :: - ;: weld - %+ expect-eq - !> (gas:atom-map ~ ~[[0^%b] [1^%c] [2^%d] [4^%f] [5^%g] [6^%g]]) - !> +.b - :: - %+ expect-eq - !> (flop (items-from-keys (gulf 0 5))) - !> -.b - == -:: -++ test-ordered-map-uni ^- tang - :: - =/ a=(tree [@ud @tas]) (gas:atom-map ~ (scag 4 test-items)) - =/ b=(tree [@ud @tas]) (gas:atom-map ~ (slag 4 test-items)) - :: - =/ c (uni:atom-map a b) - :: - %+ expect-eq - !> (gas:atom-map ~ test-items) - !> c --- diff --git a/pkg/arvo/tests/sys/zuse/ordered-map.hoon b/pkg/arvo/tests/sys/zuse/ordered-map.hoon index f1ae62d5f..ad9f24a90 100644 --- a/pkg/arvo/tests/sys/zuse/ordered-map.hoon +++ b/pkg/arvo/tests/sys/zuse/ordered-map.hoon @@ -53,55 +53,55 @@ !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f]]) !> b :: -::++ test-ordered-map-subset ^- tang -:: :: -:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) -:: :: -:: =/ b (subset:atom-map a `0 `4) -:: :: -:: %+ expect-eq -:: !> (gas:atom-map ~ ~[[1^%b] [2^%c] [3^%d]]) -:: !> b -:::: -::++ test-ordered-map-null-start-subset ^- tang -:: :: -:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) -:: :: -:: =/ b (subset:atom-map a ~ `5) -:: :: -:: %+ expect-eq -:: !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e]]) -:: !> b -:::: -::++ test-ordered-map-null-end-subset ^- tang -:: :: -:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) -:: :: -:: =/ b (subset:atom-map a `1 ~) -:: :: -:: %+ expect-eq -:: !> (gas:atom-map ~ ~[[2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) -:: !> b -:::: -::++ test-ordered-map-double-null-subset ^- tang -:: :: -:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) -:: :: -:: =/ b (subset:atom-map a ~ ~) -:: :: -:: %+ expect-eq -:: !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) -:: !> b -:::: -::++ test-ordered-map-not-found-start-subset ^- tang -:: :: -:: =/ a=(tree [@ud @tas]) (gas:atom-map ~ ~[[1^%b]]) -:: :: -:: =/ b (subset:atom-map a `0 ~) -:: :: -:: %+ expect-eq -:: !> (gas:atom-map ~ ~[[1^%b]]) -:: !> b +++ test-ordered-map-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a `0 `4) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[1^%b] [2^%c] [3^%d]]) + !> b +:: +++ test-ordered-map-null-start-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a ~ `5) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e]]) + !> b +:: +++ test-ordered-map-null-end-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a `1 ~) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) + !> b +:: +++ test-ordered-map-double-null-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ test-items) + :: + =/ b (subset:atom-map a ~ ~) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[0^%a] [1^%b] [2^%c] [3^%d] [4^%e] [5^%f] [6^%g]]) + !> b +:: +++ test-ordered-map-not-found-start-subset ^- tang + :: + =/ a=(tree [@ud @tas]) (gas:atom-map ~ ~[[1^%b]]) + :: + =/ b (subset:atom-map a `0 ~) + :: + %+ expect-eq + !> (gas:atom-map ~ ~[[1^%b]]) + !> b :: ++ test-ordered-map-traverse ^- tang :: From f76759b9e0a53daab9f0a220357d176a7ff41315 Mon Sep 17 00:00:00 2001 From: Logan Allen Date: Tue, 21 Jul 2020 14:39:42 -0700 Subject: [PATCH 8/8] zuse: added docstring and warning --- pkg/arvo/sys/zuse.hoon | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/arvo/sys/zuse.hoon b/pkg/arvo/sys/zuse.hoon index 5dcdece72..5b02b3e29 100644 --- a/pkg/arvo/sys/zuse.hoon +++ b/pkg/arvo/sys/zuse.hoon @@ -7071,6 +7071,9 @@ -- -- :: +:: +mop: constructs and validates ordered ordered map based on key, +:: val, and comparator gate +:: ++ mop |* [key=mold value=mold] |= ord=$-([key key] ?) @@ -7088,6 +7091,9 @@ :: smallest key can be popped off the head. If $key is `@` and :: .compare is +lte, then the numerically smallest item is the head. :: +:: WARNING: ordered-map will not work properly if two keys can be +:: unequal under noun equality but equal via the compare gate +:: ++ ordered-map |* [key=mold val=mold] => |%