aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/data/coll/dict.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/data/coll/dict.lux')
-rw-r--r--stdlib/source/lux/data/coll/dict.lux248
1 files changed, 124 insertions, 124 deletions
diff --git a/stdlib/source/lux/data/coll/dict.lux b/stdlib/source/lux/data/coll/dict.lux
index 5ab078e28..5b61830d5 100644
--- a/stdlib/source/lux/data/coll/dict.lux
+++ b/stdlib/source/lux/data/coll/dict.lux
@@ -1,4 +1,4 @@
-(;module:
+(.module:
lux
(lux (control hash
[eq #+ Eq])
@@ -97,58 +97,58 @@
## which is 1/4 of the branching factor (or a left-shift 2).
(def: demotion-threshold
Nat
- (bit;shift-left (n/- +2 branching-exponent) +1))
+ (bit.shift-left (n/- +2 branching-exponent) +1))
## The threshold on which #Base nodes are promoted to #Hierarchy nodes,
## which is 1/2 of the branching factor (or a left-shift 1).
(def: promotion-threshold
Nat
- (bit;shift-left (n/- +1 branching-exponent) +1))
+ (bit.shift-left (n/- +1 branching-exponent) +1))
## The size of hierarchy-nodes, which is 2^(branching-exponent).
(def: hierarchy-nodes-size
Nat
- (bit;shift-left branching-exponent +1))
+ (bit.shift-left branching-exponent +1))
## The cannonical empty node, which is just an empty #Base node.
(def: empty
Node
- (#Base clean-bitmap (array;new +0)))
+ (#Base clean-bitmap (array.new +0)))
## Expands a copy of the array, to have 1 extra slot, which is used
## for storing the value.
(def: (insert! idx value old-array)
(All [a] (-> Index a (Array a) (Array a)))
- (let [old-size (array;size old-array)]
- (|> ## (array;new (n/inc old-size))
+ (let [old-size (array.size old-array)]
+ (|> ## (array.new (n/inc old-size))
(: (Array ($ +0))
- (array;new (n/inc old-size)))
- (array;copy idx +0 old-array +0)
- (array;write idx value)
- (array;copy (n/- idx old-size) idx old-array (n/inc idx)))))
+ (array.new (n/inc old-size)))
+ (array.copy idx +0 old-array +0)
+ (array.write idx value)
+ (array.copy (n/- idx old-size) idx old-array (n/inc idx)))))
## Creates a copy of an array with an index set to a particular value.
(def: (update! idx value array)
(All [a] (-> Index a (Array a) (Array a)))
- (|> array array;clone (array;write idx value)))
+ (|> array array.clone (array.write idx value)))
## Creates a clone of the array, with an empty position at index.
(def: (vacant! idx array)
(All [a] (-> Index (Array a) (Array a)))
- (|> array array;clone (array;delete idx)))
+ (|> array array.clone (array.delete idx)))
## Shrinks a copy of the array by removing the space at index.
(def: (remove! idx array)
(All [a] (-> Index (Array a) (Array a)))
- (let [new-size (n/dec (array;size array))]
- (|> (array;new new-size)
- (array;copy idx +0 array +0)
- (array;copy (n/- idx new-size) (n/inc idx) array idx))))
+ (let [new-size (n/dec (array.size array))]
+ (|> (array.new new-size)
+ (array.copy idx +0 array +0)
+ (array.copy (n/- idx new-size) (n/inc idx) array idx))))
## Given a top-limit for indices, produces all indices in [0, R).
(def: indices-for
(-> Nat (List Index))
- (|>> n/dec (list;n/range +0)))
+ (|>> n/dec (list.n/range +0)))
## Increases the level-shift by the branching-exponent, to explore
## levels further down the tree.
@@ -162,13 +162,13 @@
## to a particular level, and uses that as an index into the array.
(def: (level-index level hash)
(-> Level Hash-Code Index)
- (bit;and hierarchy-mask
- (bit;shift-right level hash)))
+ (bit.and hierarchy-mask
+ (bit.shift-right level hash)))
## A mechanism to go from indices to bit-positions.
(def: (->bit-position index)
(-> Index BitPosition)
- (bit;shift-left index +1))
+ (bit.shift-left index +1))
## The bit-position within a base that a given hash-code would have.
(def: (bit-position level hash)
@@ -177,7 +177,7 @@
(def: (bit-position-is-set? bit bitmap)
(-> BitPosition BitMap Bool)
- (not (n/= clean-bitmap (bit;and bit bitmap))))
+ (not (n/= clean-bitmap (bit.and bit bitmap))))
## Figures out whether a bitmap only contains a single bit-position.
(def: only-bit-position?
@@ -186,17 +186,17 @@
(def: (set-bit-position bit bitmap)
(-> BitPosition BitMap BitMap)
- (bit;or bit bitmap))
+ (bit.or bit bitmap))
(def: unset-bit-position
(-> BitPosition BitMap BitMap)
- bit;xor)
+ bit.xor)
## Figures out the size of a bitmap-indexed array by counting all the
## 1s within the bitmap.
(def: bitmap-size
(-> BitMap Nat)
- bit;count)
+ bit.count)
## A mask that, for a given bit position, only allows all the 1s prior
## to it, which would indicate the bitmap-size (and, thus, index)
@@ -208,14 +208,14 @@
## The index on the base array, based on it's bit-position.
(def: (base-index bit-position bitmap)
(-> BitPosition BitMap Index)
- (bitmap-size (bit;and (bit-position-mask bit-position)
+ (bitmap-size (bit.and (bit-position-mask bit-position)
bitmap)))
## Produces the index of a KV-pair within a #Collisions node.
(def: (collision-index Hash<k> key colls)
(All [k v] (-> (Hash k) k (Collisions k v) (Maybe Index)))
- (:: Monad<Maybe> map product;left
- (array;find+ (function [idx [key' val']]
+ (:: Monad<Maybe> map product.left
+ (array.find+ (function [idx [key' val']]
(:: Hash<k> = key key'))
colls)))
@@ -223,22 +223,22 @@
## nodes to save space.
(def: (demote-hierarchy except-idx [h-size h-array])
(All [k v] (-> Index (Hierarchy k v) [BitMap (Base k v)]))
- (product;right (list/fold (function [idx [insertion-idx node]]
+ (product.right (list/fold (function [idx [insertion-idx node]]
(let [[bitmap base] node]
- (case (array;read idx h-array)
- #;None [insertion-idx node]
- (#;Some sub-node) (if (n/= except-idx idx)
+ (case (array.read idx h-array)
+ #.None [insertion-idx node]
+ (#.Some sub-node) (if (n/= except-idx idx)
[insertion-idx node]
[(n/inc insertion-idx)
[(set-bit-position (->bit-position idx) bitmap)
- (array;write insertion-idx (#;Left sub-node) base)]])
+ (array.write insertion-idx (#.Left sub-node) base)]])
)))
[+0 [clean-bitmap
- ## (array;new (n/dec h-size))
+ ## (array.new (n/dec h-size))
(: (Base ($ +0) ($ +1))
- (array;new (n/dec h-size)))
+ (array.new (n/dec h-size)))
]]
- (list;indices (array;size h-array)))))
+ (list.indices (array.size h-array)))))
## When #Base nodes grow too large, they're promoted to #Hierarchy to
## add some depth to the tree and help keep it's balance.
@@ -250,26 +250,26 @@
(Hash k) Level
BitMap (Base k v)
(Array (Node k v))))
- (product;right (list/fold (function [hierarchy-idx (^@ default [base-idx h-array])]
+ (product.right (list/fold (function [hierarchy-idx (^@ default [base-idx h-array])]
(if (bit-position-is-set? (->bit-position hierarchy-idx)
bitmap)
[(n/inc base-idx)
- (case (array;read base-idx base)
- (#;Some (#;Left sub-node))
- (array;write hierarchy-idx sub-node h-array)
+ (case (array.read base-idx base)
+ (#.Some (#.Left sub-node))
+ (array.write hierarchy-idx sub-node h-array)
- (#;Some (#;Right [key' val']))
- (array;write hierarchy-idx
+ (#.Some (#.Right [key' val']))
+ (array.write hierarchy-idx
(put' (level-up level) (:: Hash<k> hash key') key' val' Hash<k> empty)
h-array)
- #;None
+ #.None
(undefined))]
default))
[+0
- ## (array;new hierarchy-nodes-size)
+ ## (array.new hierarchy-nodes-size)
(: (Array (Node ($ +0) ($ +1)))
- (array;new hierarchy-nodes-size))
+ (array.new hierarchy-nodes-size))
]
hierarchy-indices)))
@@ -279,7 +279,7 @@
(def: (empty?' node)
(All [k v] (-> (Node k v) Bool))
(case node
- (^~ (#Base ;;clean-bitmap _))
+ (^~ (#Base ..clean-bitmap _))
true
_
@@ -292,15 +292,15 @@
## a sub-node. If impossible, I introduced a new singleton sub-node.
(#Hierarchy _size hierarchy)
(let [idx (level-index level hash)
- ## [_size' sub-node] (case (array;read idx hierarchy)
- ## (#;Some sub-node)
+ ## [_size' sub-node] (case (array.read idx hierarchy)
+ ## (#.Some sub-node)
## [_size sub-node]
## _
## [(n/inc _size) empty])
[_size' sub-node] (: [Nat (Node ($ +0) ($ +1))]
- (case (array;read idx hierarchy)
- (#;Some sub-node)
+ (case (array.read idx hierarchy)
+ (#.Some sub-node)
[_size sub-node]
_
@@ -317,33 +317,33 @@
(if (bit-position-is-set? bit bitmap)
## If so...
(let [idx (base-index bit bitmap)]
- (case (array;read idx base)
- #;None
+ (case (array.read idx base)
+ #.None
(undefined)
## If it's being used by a node, I add the KV to it.
- (#;Some (#;Left sub-node))
+ (#.Some (#.Left sub-node))
(let [sub-node' (put' (level-up level) hash key val Hash<k> sub-node)]
- (#Base bitmap (update! idx (#;Left sub-node') base)))
+ (#Base bitmap (update! idx (#.Left sub-node') base)))
## Otherwise, if it's being used by a KV, I compare the keys.
- (#;Some (#;Right key' val'))
+ (#.Some (#.Right key' val'))
(if (:: Hash<k> = key key')
## If the same key is found, I replace the value.
- (#Base bitmap (update! idx (#;Right key val) base))
+ (#Base bitmap (update! idx (#.Right key val) base))
## Otherwise, I compare the hashes of the keys.
(#Base bitmap (update! idx
- (#;Left (let [hash' (:: Hash<k> hash key')]
+ (#.Left (let [hash' (:: Hash<k> hash key')]
(if (n/= hash hash')
## If the hashes are
## the same, a new
## #Collisions node
## is added.
- (#Collisions hash (|> ## (array;new +2)
+ (#Collisions hash (|> ## (array.new +2)
(: (Array [($ +0) ($ +1)])
- (array;new +2))
- (array;write +0 [key' val'])
- (array;write +1 [key val])))
+ (array.new +2))
+ (array.write +0 [key' val'])
+ (array.write +1 [key val])))
## Otherwise, I can
## just keep using
## #Base nodes, so I
@@ -362,12 +362,12 @@
## KV-pair as a singleton node to it.
(#Hierarchy (n/inc base-count)
(|> (promote-base put' Hash<k> level bitmap base)
- (array;write (level-index level hash)
+ (array.write (level-index level hash)
(put' (level-up level) hash key val Hash<k> empty))))
## Otherwise, I just resize the #Base node to accommodate the
## new KV-pair.
(#Base (set-bit-position bit bitmap)
- (insert! (base-index bit bitmap) (#;Right [key val]) base))))))
+ (insert! (base-index bit bitmap) (#.Right [key val]) base))))))
## For #Collisions nodes, I compare the hashes.
(#Collisions _hash _colls)
@@ -377,19 +377,19 @@
(case (collision-index Hash<k> key _colls)
## If the key was already present in the collisions-list, it's
## value gets updated.
- (#;Some coll-idx)
+ (#.Some coll-idx)
(#Collisions _hash (update! coll-idx [key val] _colls))
## Otherwise, the KV-pair is added to the collisions-list.
- #;None
- (#Collisions _hash (insert! (array;size _colls) [key val] _colls)))
+ #.None
+ (#Collisions _hash (insert! (array.size _colls) [key val] _colls)))
## If the hashes are not equal, I create a new #Base node that
## contains the old #Collisions node, plus the new KV-pair.
(|> (#Base (bit-position level _hash)
- (|> ## (array;new +1)
+ (|> ## (array.new +1)
(: (Base ($ +0) ($ +1))
- (array;new +1))
- (array;write +0 (#;Left node))))
+ (array.new +1))
+ (array.write +0 (#.Left node))))
(put' level hash key val Hash<k>)))
))
@@ -400,13 +400,13 @@
## the Hash-Code.
(#Hierarchy h-size h-array)
(let [idx (level-index level hash)]
- (case (array;read idx h-array)
+ (case (array.read idx h-array)
## If not, there's nothing to remove.
- #;None
+ #.None
node
## But if there is, try to remove the key from the sub-node.
- (#;Some sub-node)
+ (#.Some sub-node)
(let [sub-node' (remove' (level-up level) hash key Hash<k> sub-node)]
## Then check if a removal was actually done.
(if (is sub-node sub-node')
@@ -429,13 +429,13 @@
(let [bit (bit-position level hash)]
(if (bit-position-is-set? bit bitmap)
(let [idx (base-index bit bitmap)]
- (case (array;read idx base)
- #;None
+ (case (array.read idx base)
+ #.None
(undefined)
## If set, check if it's a sub-node, and remove the KV
## from it.
- (#;Some (#;Left sub-node))
+ (#.Some (#.Left sub-node))
(let [sub-node' (remove' (level-up level) hash key Hash<k> sub-node)]
## Verify that it was removed.
(if (is sub-node sub-node')
@@ -454,10 +454,10 @@
## But, if it did not come out empty, then the
## position is kept, and the node gets updated.
(#Base bitmap
- (update! idx (#;Left sub-node') base)))))
+ (update! idx (#.Left sub-node') base)))))
## If, however, there was a KV-pair instead of a sub-node.
- (#;Some (#;Right [key' val']))
+ (#.Some (#.Right [key' val']))
## Check if the keys match.
(if (:: Hash<k> = key key')
## If so, remove the KV-pair and unset the BitPosition.
@@ -472,12 +472,12 @@
(#Collisions _hash _colls)
(case (collision-index Hash<k> key _colls)
## If not, then there's nothing to remove.
- #;None
+ #.None
node
## But if so, then check the size of the collisions list.
- (#;Some idx)
- (if (n/= +1 (array;size _colls))
+ (#.Some idx)
+ (if (n/= +1 (array.size _colls))
## If there's only one left, then removing it leaves us with
## an empty node.
empty
@@ -490,31 +490,31 @@
(case node
## For #Hierarchy nodes, just look-up the key on its children.
(#Hierarchy _size hierarchy)
- (case (array;read (level-index level hash) hierarchy)
- #;None #;None
- (#;Some sub-node) (get' (level-up level) hash key Hash<k> sub-node))
+ (case (array.read (level-index level hash) hierarchy)
+ #.None #.None
+ (#.Some sub-node) (get' (level-up level) hash key Hash<k> sub-node))
## For #Base nodes, check the leaves, and recursively check the branches.
(#Base bitmap base)
(let [bit (bit-position level hash)]
(if (bit-position-is-set? bit bitmap)
- (case (array;read (base-index bit bitmap) base)
- #;None
+ (case (array.read (base-index bit bitmap) base)
+ #.None
(undefined)
- (#;Some (#;Left sub-node))
+ (#.Some (#.Left sub-node))
(get' (level-up level) hash key Hash<k> sub-node)
- (#;Some (#;Right [key' val']))
+ (#.Some (#.Right [key' val']))
(if (:: Hash<k> = key key')
- (#;Some val')
- #;None))
- #;None))
+ (#.Some val')
+ #.None))
+ #.None))
## For #Collisions nodes, do a linear scan of all the known KV-pairs.
(#Collisions _hash _colls)
- (:: Monad<Maybe> map product;right
- (array;find (|>> product;left (:: Hash<k> = key))
+ (:: Monad<Maybe> map product.right
+ (array.find (|>> product.left (:: Hash<k> = key))
_colls))
))
@@ -527,12 +527,12 @@
(#Base _ base)
(array/fold n/+ +0 (array/map (function [sub-node']
(case sub-node'
- (#;Left sub-node) (size' sub-node)
- (#;Right _) +1))
+ (#.Left sub-node) (size' sub-node)
+ (#.Right _) +1))
base))
(#Collisions hash colls)
- (array;size colls)
+ (array.size colls)
))
(def: (entries' node)
@@ -540,28 +540,28 @@
(case node
(#Hierarchy _size hierarchy)
(array/fold (function [sub-node tail] (list/compose (entries' sub-node) tail))
- #;Nil
+ #.Nil
hierarchy)
(#Base bitmap base)
(array/fold (function [branch tail]
(case branch
- (#;Left sub-node)
+ (#.Left sub-node)
(list/compose (entries' sub-node) tail)
- (#;Right [key' val'])
- (#;Cons [key' val'] tail)))
- #;Nil
+ (#.Right [key' val'])
+ (#.Cons [key' val'] tail)))
+ #.Nil
base)
(#Collisions hash colls)
- (array/fold (function [[key' val'] tail] (#;Cons [key' val'] tail))
- #;Nil
+ (array/fold (function [[key' val'] tail] (#.Cons [key' val'] tail))
+ #.Nil
colls)))
## [Exports]
(type: #export (Dict k v)
- {#;doc "A dictionary implemented as a Hash-Array Mapped Trie (HAMT)."}
+ {#.doc "A dictionary implemented as a Hash-Array Mapped Trie (HAMT)."}
{#hash (Hash k)
#root (Node k v)})
@@ -588,29 +588,29 @@
(def: #export (contains? key dict)
(All [k v] (-> k (Dict k v) Bool))
(case (get key dict)
- #;None false
- (#;Some _) true))
+ #.None false
+ (#.Some _) true))
(def: #export (put~ key val dict)
- {#;doc "Only puts the KV-pair if the key is not already present."}
+ {#.doc "Only puts the KV-pair if the key is not already present."}
(All [k v] (-> k v (Dict k v) (Dict k v)))
(if (contains? key dict)
dict
(put key val dict)))
(def: #export (update key f dict)
- {#;doc "Transforms the value located at key (if available), using the given function."}
+ {#.doc "Transforms the value located at key (if available), using the given function."}
(All [k v] (-> k (-> v v) (Dict k v) (Dict k v)))
(case (get key dict)
- #;None
+ #.None
dict
- (#;Some val)
+ (#.Some val)
(put key (f val) dict)))
(def: #export size
(All [k v] (-> (Dict k v) Nat))
- (|>> product;right size'))
+ (|>> product.right size'))
(def: #export empty?
(All [k v] (-> (Dict k v) Bool))
@@ -618,7 +618,7 @@
(def: #export (entries dict)
(All [k v] (-> (Dict k v) (List [k v])))
- (entries' (product;right dict)))
+ (entries' (product.right dict)))
(def: #export (from-list Hash<k> kvs)
(All [k v] (-> (Hash k) (List [k v]) (Dict k v)))
@@ -632,12 +632,12 @@
(All [k v] (-> (Dict k v) (List <elem-type>)))
(|> dict entries (list/map <side>)))]
- [keys k product;left]
- [values v product;right]
+ [keys k product.left]
+ [values v product.right]
)
(def: #export (merge dict2 dict1)
- {#;doc "Merges 2 dictionaries.
+ {#.doc "Merges 2 dictionaries.
If any collisions with keys occur, the values of dict2 will overwrite those of dict1."}
(All [k v] (-> (Dict k v) (Dict k v) (Dict k v)))
@@ -646,16 +646,16 @@
(entries dict2)))
(def: #export (merge-with f dict2 dict1)
- {#;doc "Merges 2 dictionaries.
+ {#.doc "Merges 2 dictionaries.
If any collisions with keys occur, a new value will be computed by applying 'f' to the values of dict2 and dict1."}
(All [k v] (-> (-> v v v) (Dict k v) (Dict k v) (Dict k v)))
(list/fold (function [[key val2] dict]
(case (get key dict)
- #;None
+ #.None
(put key val2 dict)
- (#;Some val1)
+ (#.Some val1)
(put key (f val2 val1) dict)))
dict1
(entries dict2)))
@@ -663,22 +663,22 @@
(def: #export (re-bind from-key to-key dict)
(All [k v] (-> k k (Dict k v) (Dict k v)))
(case (get from-key dict)
- #;None
+ #.None
dict
- (#;Some val)
+ (#.Some val)
(|> dict
(remove from-key)
(put to-key val))))
(def: #export (select keys dict)
- {#;doc "Creates a sub-set of the given dict, with only the specified keys."}
+ {#.doc "Creates a sub-set of the given dict, with only the specified keys."}
(All [k v] (-> (List k) (Dict k v) (Dict k v)))
(let [[Hash<k> _] dict]
(list/fold (function [key new-dict]
(case (get key dict)
- #;None new-dict
- (#;Some val) (put key val new-dict)))
+ #.None new-dict
+ (#.Some val) (put key val new-dict)))
(new Hash<k>)
keys)))
@@ -687,9 +687,9 @@
(def: (= test subject)
(and (n/= (size test)
(size subject))
- (list;every? (function [k]
+ (list.every? (function [k]
(case [(get k test) (get k subject)]
- [(#;Some tk) (#;Some sk)]
+ [(#.Some tk) (#.Some sk)]
(:: Eq<v> = tk sk)
_