++mop
Ordered map mold builder
Constructs and validates an ordered map based on key type, value type and a comparator gate.
Ordinary map
s are always ordered by the ++mug
hash of their keys, while mop
s are ordered by a comparator gate of your choosing.
Accepts
++mop
has two layers, the first is a wet gate that takes two molds:
key
is amold
, the type of the map key.value
is amold
, the type of the map value.
The wet gate produces a dry gate that takes:
ord
is a binary comparatorgate
of$-([key key] ?)
used to determine item ordering. It produces.y
if the first key should be first, and.n
if it should be second.
Warning:
Ordered maps will not work properly if two keys can be unequal under noun equality but equal via the compare gate.
Produces
A mold
.
Source
++ mop|* [key=mold value=mold]|= ord=$-([key key] ?)|= a=*=/ b ;;((tree [key=key val=value]) a)?> (apt:((on key value) ord) b)b
Examples
> *((mop @ @) gth){}
Descending order:
> (gas:((on @ @) gth) *((mop @ @) gth) 1^1 2^2 3^3 ~){[key=3 val=3] [key=2 val=2] [key=1 val=1]}
Ascending order:
> (gas:((on @ @) lth) *((mop @ @) lth) 1^1 2^2 3^3 ~){[key=1 val=1] [key=2 val=2] [key=3 val=3]}
Molding a correctly ordered mop
> =a (gas:((on @ @) gth) *((mop @ @) gth) 1^1 2^2 3^3 ~)> (((mop @ @) gth) a){[key=3 val=3] [key=2 val=2] [key=1 val=1]}
Molding an incorrectly ordered mop:
> =a (malt 1^1 2^2 3^3 4^4 5^5 ~)> (((mop @ @) gth) a)dojo: hoon expression failed
Note you can't use ordinary map
constructors like ++malt
to make a mop
as it'll be in the wrong order.
++ordered-map
A synonym for ++on
.
Source
++ ordered-map on
++on
Ordered map operations
Container arm for mop
operation arms. A mop
is an ordered set of key-value pairs.
Accepts
++on
has two layers, the first is a wet gate that takes two molds:
key
is amold
, the type of the map keys.val
is amold
, the type of the map values.
The wet gate produces a dry gate that takes:
compare
is a binary comparatorgate
of$-([key key] ?)
used to determine item ordering. It produces.y
if the first key should be first, and.n
if it should be second.
Produces
A core
whose arms perform the various mop
operations.
Source
++ on~/ %on|* [key=mold val=mold]=> |%+$ item [key=key val=val]--~% %comp +>+ ~|= compare=$-([key key] ?)~% %core + ~|%
Examples
> *((on @ @) gth)< 20.htd1.ogd[ compare=<1|xpg [[@ @] [@ @] ?(%.y %.n)]>< 1.twi1.wlm[ [ key=<1.vde [* [our=@p now=@da eny=@uvJ] <17.ayh 34.ygp 14.usy 54.fbg 77.kga 232.mmf 51.qbt 123.ppa 46.hgz 1.pnw %140>]>val=<1.vde [* [our=@p now=@da eny=@uvJ] <17.ayh 34.ygp 14.usy 54.fbg 77.kga 232.mmf 51.qbt 123.ppa 46.hgz 1.pnw %140>]>]<17.ayh 34.ygp 14.usy 54.fbg 77.kga 232.mmf 51.qbt 123.ppa 46.hgz 1.pnw %140>]>]>
Here are the core's arms:
> (sloe -:!>(((on @ @) gth)))~[%run%del%get%apt%dip%has%all%gas%pry%nip%lot%tab%tap%bap%ram%got%any%pop%uni%put]
++all:on
Apply logical AND boolean test on all items.
Accepts
a
is a mop
.
b
is a gate
of the type $-([key val] ?)
, where the type of key
and val
match those of the mop
.
Produces
A ?
.
Source
++ all~/ %all|= [a=(tree item) b=$-(item ?)]^- ?|-?~ a&?&((b n.a) $(a l.a) $(a r.a))
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> (all:myon mymop |=([key=@ val=@] (gte 3 val)))%.y> (all:myon mymop |=([key=@ val=@] (gte 2 val)))%.n
++any:on
Apply logical OR boolean test on all items.
Accepts
a
is a mop
.
b
is a gate
of the type $-([key val] ?)
, where the type of key
and val
match those of the mop
.
Produces
A ?
.
Source
++ any~/ %any|= [a=(tree item) b=$-(item ?)]|- ^- ??~ a|?|((b n.a) $(a l.a) $(a r.a))
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> (any:myon mymop |=([key=@ val=@] =(1 val)))%.y> (any:myon mymop |=([key=@ val=@] =(4 val)))%.n
++apt:on
Verify horizontal and vertical orderings.
Accepts
a
is a mop
.
Produces
A ?
.
Source
++ apt~/ %apt|= a=(tree item)=| [l=(unit key) r=(unit key)]|- ^- ??~ a %.y?& ?~(l %.y (compare key.n.a u.l))?~(r %.y (compare u.r key.n.a))?~(l.a %.y &((mor key.n.a key.n.l.a) $(a l.a, l `key.n.a)))?~(r.a %.y &((mor key.n.a key.n.r.a) $(a r.a, r `key.n.a)))==
Examples
Incorrect order:
> =mymap (malt 1^1 2^2 3^3 ~)> =myon ((on @ @) gth)> (apt:myon mymap)%.n
Correct order:
> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> (apt:myon mymop)%.y
++bap:on
Convert to list, right to left
Accepts
a
is a mop
.
Produces
A (list [key val])
, where key
and val
are the types of the keys and values in the mop
.
Source
++ bap~/ %bap|= a=(tree item)^- (list item)=| b=(list item)|- ^+ b?~ a b$(a r.a, b [n.a $(a l.a)])
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> mymop{[key=3 val=3] [key=2 val=2] [key=1 val=1]}> (bap:myon mymop)~[[key=1 val=1] [key=2 val=2] [key=3 val=3]]
++del:on
Delete an item from a mop
if it exists, producing its value if it's deleted, and a new mop
.
Accepts
a
is a mop
.
b
is a noun, the type of the keys in a
.
Produces
A cell of a (unit val)
and a mop
.
Source
++ del~/ %del|= [a=(tree item) =key]^- [(unit val) (tree item)]?~ a [~ ~]?: =(key key.n.a)[`val.n.a (nip a)]?: (compare key key.n.a)=+ [found lef]=$(a l.a)[found a(l lef)]=+ [found rig]=$(a r.a)[found a(r rig)]
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> (del:myon mymop 2)[[~ 2] {[key=3 val=3] [key=1 val=1]}]> (del:myon mymop 4)[~ {[key=3 val=3] [key=2 val=2] [key=1 val=1]}]
+dip:on
Stateful partial inorder traversal
Mutates state
on each run of gate f
. Traverses from left to right. Stops when f
produces stop=%.y
, or else runs all the way to the end. Each run of f
can replace an item's value or delete the item.
Accepts
++dip
is a wet gate that takes state
, which is a mold
. The wet gate produces a dry gate that takes:
a
is amop
.state
is the initial value for the state.f
is a gate of the type$-([state item] [(unit val) stop=? state])
. It takes a pair of the current state and a key-value pair from themop
. It produces a triple of:(unit val)
a new value for the current item. If it is null, the item is deleted. If you don't want to modify the value, you just give it back the same one you received.stop
is.y
if traversal should end here, and.n
if it should continue.state
is a new value for thestate
.
Produces
A cell of the final state
and the new, possibly modified, mop
.
Source
++ dip~/ %dip|* state=mold|= $: a=(tree item)=statef=$-([state item] [(unit val) ? state])==^+ [state a]=/ acc [stop=`?`%.n state=state]=< abet =< main|%++ this .++ abet [state.acc a]++ main^+ this?: =(~ a) this?: stop.acc this=. this left?: stop.acc this=^ del this node=? this !stop.acc right=? a del (nip a)this++ node^+ [del=*? this]?> ?=(^ a)=^ res acc (f state.acc n.a)?~ res[del=& this][del=| this(val.n.a u.res)]++ left^+ this?~ a this=/ lef main(a l.a)lef(a a(l a.lef))++ right^+ this?~ a this=/ rig main(a r.a)rig(a a(r a.rig))--
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 4^4 5^5 ~)
Add them all up:
> ((dip:myon @) mymop 0 |=([stat=@ k=@ v=@] [`v .n (add stat v)]))[15 {[key=5 val=5] [key=4 val=4] [key=3 val=3] [key=2 val=2] [key=1 val=1]}]
Add them up, stopping when the key is less than 3:
> ((dip:myon @) mymop 0 |=([stat=@ k=@ v=@] [`v (lth 3 k) (add stat v)]))[5 {[key=5 val=5] [key=4 val=4] [key=3 val=3] [key=2 val=2] [key=1 val=1]}]
Delete items less than three:
> ((dip:myon @) mymop 0 |=([stat=@ k=@ v=@] [?:((lth k 3) ~ `v) .n (add stat v)]))[15 {[key=5 val=5] [key=4 val=4] [key=3 val=3]}]
++gas:on
Put a list of key-value pairs in a mop
.
Accepts
a
is a mop
.
b
is a list of key-value pairs, whose types match those of the mop
.
Source
++ gas~/ %gas|= [a=(tree item) b=(list item)]^- (tree item)?~ b a$(b t.b, a (put a i.b))
Examples
> =myon ((on @ @) gth)> (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 4^4 5^5 ~){[key=5 val=5] [key=4 val=4] [key=3 val=3] [key=2 val=2] [key=1 val=1]}
++get:on
Get a value at a key or null
Accepts
a
is a mop
.
b
is a noun whose type matches that of the mop's keys.
Produces
A (unit val)
, where val
is the type of the values of the mop
.
Source
++ get~/ %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)
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 4^4 5^5 ~)> (get:myon mymop 3)[~ 3]> (get:myon mymop 7)~
++got:on
Get a value at a key, crashing if it doesn't exist
Accepts
a
is a mop
.
b
is a noun whose type matches that of the mop's keys.
Produces
A noun of the type of the values of the mop
, crashing if the key doesn't exist.
Source
++ got|= [a=(tree item) b=key]^- val(need (get a b))
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 4^4 5^5 ~)> (got:myon mymop 3)3> (got:myon mymop 7)dojo: hoon expression failed
++has:on
Check for key existence
Accepts
a
is a mop
.
b
is a noun whose type matches that of the mop's keys.
Produces
A ?
.
Source
++ has~/ %has|= [a=(tree item) b=key]^- ?!=(~ (get a b))
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 4^4 5^5 ~)> (has:myon mymop 3)%.y> (has:myon mymop 7)%.n
++lot:on
Take a subset range excluding start
and/or end
, and all elements outside the range.
Accepts
tre
is a mop
.
start
is a (unit key)
, where key
is a noun whose type matches the type of the mop
keys. If non-null, this item and all those previous will be excluded.
end
is a (unit key)
, where key
is a noun whose type matches the type of the mop
keys. If non-null, this item and all those after will be excluded.
Produces
A mop
.
Source
++ lot~/ %lot|= $: 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)?> (compare 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?: =(key.n.a u.c)(nip a(l ~))?: (compare key.n.a u.c)$(a (nip a(l ~)))a(l $(a l.a))::%end?: =(u.c key.n.a)(nip a(r ~))?: (compare key.n.a u.c)a(r $(a r.a))$(a (nip a(r ~)))==--
Examples
> =myon ((on @ @) lth)> =mymop (gas:myon *((mop @ @) lth) 2^2 4^4 6^6 8^8 10^10 ~)> mymop{[key=2 val=2] [key=4 val=4] [key=6 val=6] [key=8 val=8] [key=10 val=10]}> (lot:myon mymop `3 ~){[key=4 val=4] [key=6 val=6] [key=8 val=8] [key=10 val=10]}> (lot:myon mymop `4 ~){[key=6 val=6] [key=8 val=8] [key=10 val=10]}> (lot:myon mymop ~ `8){[key=2 val=2] [key=4 val=4] [key=6 val=6]}> (lot:myon mymop `3 `7){[key=4 val=4] [key=6 val=6]}> (lot:myon mymop ~ ~){[key=2 val=2] [key=4 val=4] [key=6 val=6] [key=8 val=8] [key=10 val=10]}> (lot:myon mymop `0 `100){[key=2 val=2] [key=4 val=4] [key=6 val=6] [key=8 val=8] [key=10 val=10]}
++nip:on
Remove root (for internal use)
Accepts
a
is a mop
.
Produces
A mop
.
Source
++ nip~/ %nip|= a=(tree item)^- (tree item)?> ?=(^ 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))
Examples
Note this is for internal use, you would not normally use ++nip
.
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> mymop{[key=3 val=3] [key=2 val=2] [key=1 val=1]}> (nip:myon mymop){[key=3 val=3] [key=1 val=1]}
++pop:on
Produce head
(the leftmost item) and rest
or crash if empty
Accepts
a
is a mop
.
Produces
A cell of head
, the leftmost item, and rest
, the mop
sans its leftmost item. If the mop
was empty, it'll crash.
Source
++ pop~/ %pop|= a=(tree item)^- [head=item rest=(tree item)]?~ a !!?~ l.a [n.a r.a]=/ l $(a l.a):- head.l?: |(?=(~ rest.l) (mor key.n.a key.n.rest.l))a(l rest.l)rest.l(r a(r r.rest.l))
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> mymop{[key=3 val=3] [key=2 val=2] [key=1 val=1]}> (pop:myon mymop)[head=[key=3 val=3] rest={[key=2 val=2] [key=1 val=1]}]> (pop:myon *((mop @ @) gth))dojo: hoon expression failed
++pry:on
Produce the head (leftmost item) or null
Accepts
a
is a mop
.
Produces
A (unit item)
, where item
is a key-value pair. The unit is null if the mop was empty.
Source
++ pry~/ %pry|= a=(tree item)^- (unit item)?~ a ~|-?~ l.a `n.a$(a l.a)
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> (pry:myon mymop)[~ [key=3 val=3]]> (pry:myon *((mop @ @) gth))~
++put:on
Insert an item
Accepts
a
is a mop
.
key
is a noun whose type matches the keys in a
.
val
is a noun whose type matches the values in a
.
Produces
A mop
.
Source
++ put~/ %put|= [a=(tree item) =key =val]^- (tree item)?~ a [n=[key val] l=~ r=~]?: =(key.n.a key) a(val.n val)?: (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))=/ r $(a r.a)?> ?=(^ r)?: (mor key.n.a key.n.r)a(r r)r(l a(r l.r))
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> (put:myon mymop 7 7){[key=7 val=7] [key=3 val=3] [key=2 val=2] [key=1 val=1]}
++ram:on
Produce tail (rightmost item) or null
Accepts
a
is a mop
.
Produces
A (unit item)
where item
is a key-value pair whose type is that of the keys and values in the mop
.
Source
++ ram~/ %ram|= a=(tree item)^- (unit item)?~ a ~|-?~ r.a `n.a$(a r.a)
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> mymop{[key=3 val=3] [key=2 val=2] [key=1 val=1]}> (ram:myon mymop)[~ [key=1 val=1]]> (ram:myon *((mop @ @) gth))~
++run:on
Apply gate to transform all values in place
Accepts
a
is a mop
.
b
is a gate of $-(val *)
, where val
is the type of the values in the mop
.
Produces
A mop
.
Source
++ run~/ %run|* [a=(tree item) b=$-(val *)]|-?~ a a[n=[key.n.a (b val.n.a)] l=$(a l.a) r=$(a r.a)]
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 ~)> mymop{[key=3 val=3] [key=2 val=2] [key=1 val=1]}> `((mop @ @) gth)`(run:myon mymop succ){[key=3 val=4] [key=2 val=3] [key=1 val=2]}> `((mop @ @t) gth)`(run:myon mymop (cury add 'a')){[key=3 val='d'] [key=2 val='c'] [key=1 val='b']}
++tab:on
Tabulate a subset with a max count, maybe starting after a certain element.
Accepts
a
is a mop
.
b
is a (unit key)
. The type of key
matches the type of keys in the mop
. This specifies where to start if non-null.
c
is a @
specifying the maximum number of items to return.
Produces
A (list item)
, where item
is a key-value matching the type of the mop
.
Source
++ tab~/ %tab|= [a=(tree item) b=(unit key) c=@]^- (list item)|^(flop e:(tabulate (del-span a b) b c))::++ tabulate|= [a=(tree item) b=(unit key) c=@]^- [d=@ e=(list item)]?: ?&(?=(~ b) =(c 0))[0 ~]=| f=[d=@ e=(list item)]|- ^+ f?: ?|(?=(~ a) =(d.f c)) f=. f $(a l.a)?: =(d.f c) f=. f [+(d.f) [n.a e.f]]?:(=(d.f c) f $(a r.a))::++ del-span|= [a=(tree item) b=(unit key)]^- (tree item)?~ a a?~ b a?: =(key.n.a u.b)r.a?: (compare key.n.a u.b)$(a r.a)a(l $(a l.a))--
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 4^4 5^5 ~)> mymop{[key=5 val=5] [key=4 val=4] [key=3 val=3] [key=2 val=2] [key=1 val=1]}> (tab:myon mymop ~ 2)~[[key=5 val=5] [key=4 val=4]]> (tab:myon mymop `4 2)~[[key=3 val=3] [key=2 val=2]]> (tab:myon mymop `4 100)~[[key=3 val=3] [key=2 val=2] [key=1 val=1]]
+tap:on
Convert to list, left to right
Accepts
a
is a mop
.
Produces
A (list item)
, where item
is a key-value pair whose type matches those of the mop
.
Source
++ tap~/ %tap|= a=(tree item)^- (list item)=| b=(list item)|- ^+ b?~ a b$(a l.a, b [n.a $(a r.a)])
Examples
> =myon ((on @ @) gth)> =mymop (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 4^4 5^5 ~)> mymop{[key=5 val=5] [key=4 val=4] [key=3 val=3] [key=2 val=2] [key=1 val=1]}> (tap:myon mymop)~[[key=5 val=5] [key=4 val=4] [key=3 val=3] [key=2 val=2] [key=1 val=1]]
++uni:on
Unify two ordered maps
If the keys overlap and the values are different, the value in mop b
take precedence over the value in mop a
.
Accepts
a
is a mop
.
b
is a mop
.
Produces
A mop
.
Source
++ uni~/ %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)--
Examples
> =myon ((on @ @) gth)> =a (gas:myon *((mop @ @) gth) 1^1 2^2 3^3 4^4 5^5 ~)> =b (gas:myon *((mop @ @) gth) 2^20 4^40 6^60 ~)> (uni:myon a b){[key=6 val=60] [key=5 val=5] [key=4 val=40] [key=3 val=3] [key=2 val=20] [key=1 val=1]}