ic-mops 0.8.5 → 0.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/package.json +3 -1
  2. package/.mops/base@0.7.4/LICENSE +0 -208
  3. package/.mops/base@0.7.4/README.md +0 -64
  4. package/.mops/base@0.7.4/mops.toml +0 -5
  5. package/.mops/base@0.7.4/src/Array.mo +0 -686
  6. package/.mops/base@0.7.4/src/AssocList.mo +0 -203
  7. package/.mops/base@0.7.4/src/Blob.mo +0 -55
  8. package/.mops/base@0.7.4/src/Bool.mo +0 -44
  9. package/.mops/base@0.7.4/src/Buffer.mo +0 -1937
  10. package/.mops/base@0.7.4/src/CertifiedData.mo +0 -29
  11. package/.mops/base@0.7.4/src/Char.mo +0 -67
  12. package/.mops/base@0.7.4/src/Debug.mo +0 -15
  13. package/.mops/base@0.7.4/src/Deque.mo +0 -75
  14. package/.mops/base@0.7.4/src/Error.mo +0 -41
  15. package/.mops/base@0.7.4/src/ExperimentalCycles.mo +0 -51
  16. package/.mops/base@0.7.4/src/ExperimentalInternetComputer.mo +0 -36
  17. package/.mops/base@0.7.4/src/ExperimentalStableMemory.mo +0 -121
  18. package/.mops/base@0.7.4/src/Float.mo +0 -150
  19. package/.mops/base@0.7.4/src/Func.mo +0 -38
  20. package/.mops/base@0.7.4/src/Hash.mo +0 -83
  21. package/.mops/base@0.7.4/src/HashMap.mo +0 -229
  22. package/.mops/base@0.7.4/src/Heap.mo +0 -113
  23. package/.mops/base@0.7.4/src/Int.mo +0 -150
  24. package/.mops/base@0.7.4/src/Int16.mo +0 -159
  25. package/.mops/base@0.7.4/src/Int32.mo +0 -160
  26. package/.mops/base@0.7.4/src/Int64.mo +0 -161
  27. package/.mops/base@0.7.4/src/Int8.mo +0 -160
  28. package/.mops/base@0.7.4/src/Iter.mo +0 -220
  29. package/.mops/base@0.7.4/src/IterType.mo +0 -7
  30. package/.mops/base@0.7.4/src/List.mo +0 -433
  31. package/.mops/base@0.7.4/src/Nat.mo +0 -75
  32. package/.mops/base@0.7.4/src/Nat16.mo +0 -146
  33. package/.mops/base@0.7.4/src/Nat32.mo +0 -146
  34. package/.mops/base@0.7.4/src/Nat64.mo +0 -146
  35. package/.mops/base@0.7.4/src/Nat8.mo +0 -146
  36. package/.mops/base@0.7.4/src/None.mo +0 -19
  37. package/.mops/base@0.7.4/src/Option.mo +0 -160
  38. package/.mops/base@0.7.4/src/Order.mo +0 -46
  39. package/.mops/base@0.7.4/src/Prelude.mo +0 -33
  40. package/.mops/base@0.7.4/src/Principal.mo +0 -58
  41. package/.mops/base@0.7.4/src/RBTree.mo +0 -218
  42. package/.mops/base@0.7.4/src/Random.mo +0 -188
  43. package/.mops/base@0.7.4/src/Result.mo +0 -210
  44. package/.mops/base@0.7.4/src/Stack.mo +0 -40
  45. package/.mops/base@0.7.4/src/Text.mo +0 -615
  46. package/.mops/base@0.7.4/src/Time.mo +0 -37
  47. package/.mops/base@0.7.4/src/Trie.mo +0 -1200
  48. package/.mops/base@0.7.4/src/TrieMap.mo +0 -180
  49. package/.mops/base@0.7.4/src/TrieSet.mo +0 -97
  50. package/.mops/base@0.8.3/LICENSE +0 -208
  51. package/.mops/base@0.8.3/README.md +0 -64
  52. package/.mops/base@0.8.3/mops.toml +0 -6
  53. package/.mops/base@0.8.3/src/Array.mo +0 -717
  54. package/.mops/base@0.8.3/src/AssocList.mo +0 -404
  55. package/.mops/base@0.8.3/src/Blob.mo +0 -212
  56. package/.mops/base@0.8.3/src/Bool.mo +0 -44
  57. package/.mops/base@0.8.3/src/Buffer.mo +0 -2660
  58. package/.mops/base@0.8.3/src/CertifiedData.mo +0 -53
  59. package/.mops/base@0.8.3/src/Char.mo +0 -65
  60. package/.mops/base@0.8.3/src/Debug.mo +0 -56
  61. package/.mops/base@0.8.3/src/Deque.mo +0 -243
  62. package/.mops/base@0.8.3/src/Error.mo +0 -68
  63. package/.mops/base@0.8.3/src/ExperimentalCycles.mo +0 -151
  64. package/.mops/base@0.8.3/src/ExperimentalInternetComputer.mo +0 -60
  65. package/.mops/base@0.8.3/src/ExperimentalStableMemory.mo +0 -348
  66. package/.mops/base@0.8.3/src/Float.mo +0 -843
  67. package/.mops/base@0.8.3/src/Func.mo +0 -46
  68. package/.mops/base@0.8.3/src/Hash.mo +0 -82
  69. package/.mops/base@0.8.3/src/HashMap.mo +0 -457
  70. package/.mops/base@0.8.3/src/Heap.mo +0 -233
  71. package/.mops/base@0.8.3/src/Int.mo +0 -365
  72. package/.mops/base@0.8.3/src/Int16.mo +0 -521
  73. package/.mops/base@0.8.3/src/Int32.mo +0 -522
  74. package/.mops/base@0.8.3/src/Int64.mo +0 -522
  75. package/.mops/base@0.8.3/src/Int8.mo +0 -522
  76. package/.mops/base@0.8.3/src/Iter.mo +0 -227
  77. package/.mops/base@0.8.3/src/IterType.mo +0 -7
  78. package/.mops/base@0.8.3/src/List.mo +0 -930
  79. package/.mops/base@0.8.3/src/Nat.mo +0 -305
  80. package/.mops/base@0.8.3/src/Nat16.mo +0 -144
  81. package/.mops/base@0.8.3/src/Nat32.mo +0 -144
  82. package/.mops/base@0.8.3/src/Nat64.mo +0 -144
  83. package/.mops/base@0.8.3/src/Nat8.mo +0 -144
  84. package/.mops/base@0.8.3/src/None.mo +0 -19
  85. package/.mops/base@0.8.3/src/Option.mo +0 -154
  86. package/.mops/base@0.8.3/src/Order.mo +0 -46
  87. package/.mops/base@0.8.3/src/Prelude.mo +0 -33
  88. package/.mops/base@0.8.3/src/Principal.mo +0 -249
  89. package/.mops/base@0.8.3/src/RBTree.mo +0 -681
  90. package/.mops/base@0.8.3/src/Random.mo +0 -270
  91. package/.mops/base@0.8.3/src/Result.mo +0 -209
  92. package/.mops/base@0.8.3/src/Stack.mo +0 -93
  93. package/.mops/base@0.8.3/src/Text.mo +0 -761
  94. package/.mops/base@0.8.3/src/Time.mo +0 -36
  95. package/.mops/base@0.8.3/src/Timer.mo +0 -62
  96. package/.mops/base@0.8.3/src/Trie.mo +0 -1603
  97. package/.mops/base@0.8.3/src/TrieMap.mo +0 -392
  98. package/.mops/base@0.8.3/src/TrieSet.mo +0 -148
  99. package/network.txt +0 -1
@@ -1,681 +0,0 @@
1
- /// Key-value map implemented as a red-black tree (RBTree) with nodes storing key-value pairs.
2
- ///
3
- /// A red-black tree is a balanced binary search tree ordered by the keys.
4
- ///
5
- /// The tree data structure internally colors each of its nodes either red or black,
6
- /// and uses this information to balance the tree during the modifying operations.
7
- ///
8
- /// Creation:
9
- /// Instantiate class `RBTree<K, V>` that provides a map from keys of type `K` to values of type `V`.
10
- ///
11
- /// Example:
12
- /// ```motoko
13
- /// import RBTree "mo:base/RBTree";
14
- /// import Nat "mo:base/Nat";
15
- /// import Debug "mo:base/Debug";
16
- ///
17
- /// let tree = RBTree.RBTree<Nat, Text>(Nat.compare); // Create a new red-black tree mapping Nat to Text
18
- /// tree.put(1, "one");
19
- /// tree.put(2, "two");
20
- /// tree.put(3, "tree");
21
- /// for (entry in tree.entries()) {
22
- /// Debug.print("Entry key=" # debug_show(entry.0) # " value=\"" # entry.1 #"\"");
23
- /// }
24
- /// ```
25
- ///
26
- /// Performance:
27
- /// * Runtime: `O(log(n))` worst case cost per insertion, removal, and retrieval operation.
28
- /// * Space: `O(n)` for storing the entire tree.
29
- /// `n` denotes the number of key-value entries (i.e. nodes) stored in the tree.
30
- ///
31
- /// Note:
32
- /// * Tree operations, such as retrieval, insertion, and removal create `O(log(n))` temporary objects that become garbage.
33
- ///
34
- /// Credits:
35
- ///
36
- /// The core of this implementation is derived from:
37
- ///
38
- /// * Ken Friis Larsen's [RedBlackMap.sml](https://github.com/kfl/mosml/blob/master/src/mosmllib/Redblackmap.sml), which itself is based on:
39
- /// * Stefan Kahrs, "Red-black trees with types", Journal of Functional Programming, 11(4): 425-432 (2001), [version 1 in web appendix](http://www.cs.ukc.ac.uk/people/staff/smk/redblack/rb.html).
40
-
41
-
42
- import Debug "Debug";
43
- import I "Iter";
44
- import List "List";
45
- import Nat "Nat";
46
- import O "Order";
47
-
48
- // TODO: a faster, more compact and less indirect representation would be:
49
- // type Tree<K, V> = {
50
- // #red : (Tree<K, V>, K, V, Tree<K, V>);
51
- // #black : (Tree<K, V>, K, V, Tree<K, V>);
52
- // #leaf
53
- //};
54
- // (this inlines the colors into the variant, flattens a tuple, and removes a (now) redundant optin, for considerable heap savings.)
55
- // It would also make sense to maintain the size in a separate root for 0(1) access.
56
-
57
- // FUTURE: deprecate RBTree.mo and replace by RedBlackMap.mo, using this new representation
58
-
59
- module {
60
-
61
- /// Node color: Either red (`#R`) or black (`#B`).
62
- public type Color = { #R; #B };
63
-
64
- /// Red-black tree of nodes with key-value entries, ordered by the keys.
65
- /// The keys have the generic type `K` and the values the generic type `V`.
66
- /// Leaves are considered implicitly black.
67
- public type Tree<K, V> = {
68
- #node : (Color, Tree<K, V>, (K, ?V), Tree<K, V>);
69
- #leaf
70
- };
71
-
72
-
73
-
74
- /// A map from keys of type `K` to values of type `V` implemented as a red-black tree.
75
- /// The entries of key-value pairs are ordered by `compare` function applied to the keys.
76
- ///
77
- /// The class enables imperative usage in object-oriented-style.
78
- /// However, internally, the class uses a functional implementation.
79
- ///
80
- /// The `compare` function should implement a consistent total order among all possible values of `K` and
81
- /// for efficiency, only involves `O(1)` runtime costs without space allocation.
82
- ///
83
- /// Example:
84
- /// ```motoko name=initialize
85
- /// import RBTree "mo:base/RBTree";
86
- /// import Nat "mo:base/Nat";
87
- ///
88
- /// let tree = RBTree.RBTree<Nat, Text>(Nat.compare); // Create a map of `Nat` to `Text` using the `Nat.compare` order
89
- /// ```
90
- ///
91
- /// Costs of instantiation (only empty tree):
92
- /// Runtime: `O(1)`.
93
- /// Space: `O(1)`.
94
- public class RBTree<K, V>(compare : (K, K) -> O.Order) {
95
-
96
- var tree : Tree<K, V> = (#leaf : Tree<K, V>);
97
-
98
- /// Return a snapshot of the internal functional tree representation as sharable data.
99
- /// The returned tree representation is not affected by subsequent changes of the `RBTree` instance.
100
- ///
101
- ///
102
- /// Example:
103
- /// ```motoko include=initialize
104
- ///
105
- /// tree.put(1, "one");
106
- /// let treeSnapshot = tree.share();
107
- /// tree.put(2, "second");
108
- /// RBTree.size(treeSnapshot) // => 1 (Only the first insertion is part of the snapshot.)
109
- /// ```
110
- ///
111
- /// Useful for storing the state of a tree object as a stable variable, determining its size, pretty-printing, and sharing it across async function calls,
112
- /// i.e. passing it in async arguments or async results.
113
- ///
114
- /// Runtime: `O(1)`.
115
- /// Space: `O(1)`.
116
- public func share() : Tree<K, V> {
117
- tree
118
- };
119
-
120
- /// Reset the current state of the tree object from a functional tree representation.
121
- ///
122
- /// Example:
123
- /// ```motoko include=initialize
124
- /// import Iter "mo:base/Iter";
125
- ///
126
- /// tree.put(1, "one");
127
- /// let snapshot = tree.share(); // save the current state of the tree object in a snapshot
128
- /// tree.put(2, "two");
129
- /// tree.unshare(snapshot); // restore the tree object from the snapshot
130
- /// Iter.toArray(tree.entries()) // => [(1, "one")]
131
- /// ```
132
- ///
133
- /// Useful for restoring the state of a tree object from stable data, saved, for example, in a stable variable.
134
- ///
135
- /// Runtime: `O(1)`.
136
- /// Space: `O(1)`.
137
- public func unshare(t : Tree<K, V>) : () {
138
- tree := t
139
- };
140
-
141
-
142
- /// Retrieve the value associated with a given key, if present. Returns `null`, if the key is absent.
143
- /// The key is searched according to the `compare` function defined on the class instantiation.
144
- ///
145
- /// Example:
146
- /// ```motoko include=initialize
147
- ///
148
- /// tree.put(1, "one");
149
- /// tree.put(2, "two");
150
- ///
151
- /// tree.get(1) // => ?"one"
152
- /// ```
153
- ///
154
- /// Runtime: `O(log(n))`.
155
- /// Space: `O(1)` retained memory plus garbage, see the note below.
156
- /// where `n` denotes the number of key-value entries stored in the tree and
157
- /// assuming that the `compare` function implements an `O(1)` comparison.
158
- ///
159
- /// Note: Creates `O(log(n))` temporary objects that will be collected as garbage.
160
- public func get(key : K) : ?V {
161
- getRec(key, compare, tree)
162
- };
163
-
164
- /// Replace the value associated with a given key, if the key is present.
165
- /// Otherwise, if the key does not yet exist, insert the key-value entry.
166
- ///
167
- /// Returns the previous value of the key, if the key already existed.
168
- /// Otherwise, `null`, if the key did not yet exist before.
169
- ///
170
- /// Example:
171
- /// ```motoko include=initialize
172
- /// import Iter "mo:base/Iter";
173
- ///
174
- /// tree.put(1, "old one");
175
- /// tree.put(2, "two");
176
- ///
177
- /// ignore tree.replace(1, "new one");
178
- /// Iter.toArray(tree.entries()) // => [(1, "new one"), (2, "two")]
179
- /// ```
180
- ///
181
- /// Runtime: `O(log(n))`.
182
- /// Space: `O(1)` retained memory plus garbage, see the note below.
183
- /// where `n` denotes the number of key-value entries stored in the tree and
184
- /// assuming that the `compare` function implements an `O(1)` comparison.
185
- ///
186
- /// Note: Creates `O(log(n))` temporary objects that will be collected as garbage.
187
- public func replace(key : K, value : V) : ?V {
188
- let (t, res) = insert(tree, compare, key, value);
189
- tree := t;
190
- res
191
- };
192
-
193
- /// Insert a key-value entry in the tree. If the key already exists, it overwrites the associated value.
194
- ///
195
- /// Example:
196
- /// ```motoko include=initialize
197
- /// import Iter "mo:base/Iter";
198
- ///
199
- /// tree.put(1, "one");
200
- /// tree.put(2, "two");
201
- /// tree.put(3, "three");
202
- /// Iter.toArray(tree.entries()) // now contains three entries
203
- /// ```
204
- ///
205
- /// Runtime: `O(log(n))`.
206
- /// Space: `O(1)` retained memory plus garbage, see the note below.
207
- /// where `n` denotes the number of key-value entries stored in the tree and
208
- /// assuming that the `compare` function implements an `O(1)` comparison.
209
- ///
210
- /// Note: Creates `O(log(n))` temporary objects that will be collected as garbage.
211
- public func put(key : K, value : V) {
212
- let (t, res) = insert(tree, compare, key, value);
213
- tree := t
214
- };
215
-
216
- /// Delete the entry associated with a given key, if the key exists.
217
- /// No effect if the key is absent. Same as `remove(key)` except that it
218
- /// does not have a return value.
219
- ///
220
- /// Example:
221
- /// ```motoko include=initialize
222
- /// import Iter "mo:base/Iter";
223
- ///
224
- /// tree.put(1, "one");
225
- /// tree.put(2, "two");
226
- ///
227
- /// tree.delete(1);
228
- /// Iter.toArray(tree.entries()) // => [(2, "two")].
229
- /// ```
230
- ///
231
- /// Runtime: `O(log(n))`.
232
- /// Space: `O(1)` retained memory plus garbage, see the note below.
233
- /// where `n` denotes the number of key-value entries stored in the tree and
234
- /// assuming that the `compare` function implements an `O(1)` comparison.
235
- ///
236
- /// Note: Creates `O(log(n))` temporary objects that will be collected as garbage.
237
- public func delete(key : K) {
238
- let (res, t) = removeRec(key, compare, tree);
239
- tree := t
240
- };
241
-
242
- /// Remove the entry associated with a given key, if the key exists, and return the associated value.
243
- /// Returns `null` without any other effect if the key is absent.
244
- ///
245
- /// Example:
246
- /// ```motoko include=initialize
247
- /// import Iter "mo:base/Iter";
248
- ///
249
- /// tree.put(1, "one");
250
- /// tree.put(2, "two");
251
- ///
252
- /// ignore tree.remove(1);
253
- /// Iter.toArray(tree.entries()) // => [(2, "two")].
254
- /// ```
255
- ///
256
- /// Runtime: `O(log(n))`.
257
- /// Space: `O(1)` retained memory plus garbage, see the note below.
258
- /// where `n` denotes the number of key-value entries stored in the tree and
259
- /// assuming that the `compare` function implements an `O(1)` comparison.
260
- ///
261
- /// Note: Creates `O(log(n))` temporary objects that will be collected as garbage.
262
- public func remove(key : K) : ?V {
263
- let (res, t) = removeRec(key, compare, tree);
264
- tree := t;
265
- res
266
- };
267
-
268
- /// An iterator for the key-value entries of the map, in ascending key order.
269
- /// The iterator takes a snapshot view of the tree and is not affected by concurrent modifications.
270
- ///
271
- /// Example:
272
- /// ```motoko include=initialize
273
- /// import Debug "mo:base/Debug";
274
- ///
275
- /// tree.put(1, "one");
276
- /// tree.put(2, "two");
277
- /// tree.put(3, "two");
278
- ///
279
- /// for (entry in tree.entries()) {
280
- /// Debug.print("Entry key=" # debug_show(entry.0) # " value=\"" # entry.1 #"\"");
281
- /// }
282
- ///
283
- /// // Entry key=1 value="one"
284
- /// // Entry key=2 value="two"
285
- /// // Entry key=3 value="three"
286
- /// ```
287
- ///
288
- /// Cost of iteration over all elements:
289
- /// Runtime: `O(n)`.
290
- /// Space: `O(log(n))` retained memory plus garbage, see the note below.
291
- /// where `n` denotes the number of key-value entries stored in the tree.
292
- ///
293
- /// Note: Full tree iteration creates `O(n)` temporary objects that will be collected as garbage.
294
- public func entries() : I.Iter<(K, V)> { iter(tree, #fwd) };
295
-
296
- /// An iterator for the key-value entries of the map, in descending key order.
297
- /// The iterator takes a snapshot view of the tree and is not affected by concurrent modifications.
298
- ///
299
- /// Example:
300
- /// ```motoko include=initialize
301
- /// import Debug "mo:base/Debug";
302
- ///
303
- /// let tree = RBTree.RBTree<Nat, Text>(Nat.compare);
304
- /// tree.put(1, "one");
305
- /// tree.put(2, "two");
306
- /// tree.put(3, "two");
307
- ///
308
- /// for (entry in tree.entriesRev()) {
309
- /// Debug.print("Entry key=" # debug_show(entry.0) # " value=\"" # entry.1 #"\"");
310
- /// }
311
- ///
312
- /// // Entry key=3 value="three"
313
- /// // Entry key=2 value="two"
314
- /// // Entry key=1 value="one"
315
- /// ```
316
- ///
317
- /// Cost of iteration over all elements:
318
- /// Runtime: `O(n)`.
319
- /// Space: `O(log(n))` retained memory plus garbage, see the note below.
320
- /// where `n` denotes the number of key-value entries stored in the tree.
321
- ///
322
- /// Note: Full tree iteration creates `O(n)` temporary objects that will be collected as garbage.
323
- public func entriesRev() : I.Iter<(K, V)> { iter(tree, #bwd) };
324
-
325
- }; // end class
326
-
327
- type IterRep<X, Y> = List.List<{ #tr : Tree<X, Y>; #xy : (X, ?Y) }>;
328
-
329
- /// Get an iterator for the entries of the `tree`, in ascending (`#fwd`) or descending (`#bwd`) order as specified by `direction`.
330
- /// The iterator takes a snapshot view of the tree and is not affected by concurrent modifications.
331
- ///
332
- /// Example:
333
- /// ```motoko
334
- /// import RBTree "mo:base/RBTree";
335
- /// import Nat "mo:base/Nat";
336
- /// import Debug "mo:base/Debug";
337
- ///
338
- /// let tree = RBTree.RBTree<Nat, Text>(Nat.compare);
339
- /// tree.put(1, "one");
340
- /// tree.put(2, "two");
341
- /// tree.put(3, "two");
342
- ///
343
- /// for (entry in RBTree.iter(tree.share(), #bwd)) { // backward iteration
344
- /// Debug.print("Entry key=" # debug_show(entry.0) # " value=\"" # entry.1 #"\"");
345
- /// }
346
- ///
347
- /// // Entry key=3 value="three"
348
- /// // Entry key=2 value="two"
349
- /// // Entry key=1 value="one"
350
- /// ```
351
- ///
352
- /// Cost of iteration over all elements:
353
- /// Runtime: `O(n)`.
354
- /// Space: `O(log(n))` retained memory plus garbage, see the note below.
355
- /// where `n` denotes the number of key-value entries stored in the tree.
356
- ///
357
- /// Note: Full tree iteration creates `O(n)` temporary objects that will be collected as garbage.
358
- public func iter<X, Y>(tree : Tree<X, Y>, direction : { #fwd; #bwd }) : I.Iter<(X, Y)> {
359
- object {
360
- var trees : IterRep<X, Y> = ?(#tr(tree), null);
361
- public func next() : ?(X, Y) {
362
- switch (direction, trees) {
363
- case (_, null) { null };
364
- case (_, ?(#tr(#leaf), ts)) {
365
- trees := ts;
366
- next()
367
- };
368
- case (_, ?(#xy(xy), ts)) {
369
- trees := ts;
370
- switch (xy.1) {
371
- case null { next() };
372
- case (?y) { ?(xy.0, y) }
373
- }
374
- };
375
- case (#fwd, ?(#tr(#node(_, l, xy, r)), ts)) {
376
- trees := ?(#tr(l), ?(#xy(xy), ?(#tr(r), ts)));
377
- next()
378
- };
379
- case (#bwd, ?(#tr(#node(_, l, xy, r)), ts)) {
380
- trees := ?(#tr(r), ?(#xy(xy), ?(#tr(l), ts)));
381
- next()
382
- }
383
- }
384
- }
385
- }
386
- };
387
-
388
- /// Remove the value associated with a given key.
389
- func removeRec<X, Y>(x : X, compare : (X, X) -> O.Order, t : Tree<X, Y>) : (?Y, Tree<X, Y>) {
390
- let (t1, r) = remove(t, compare, x);
391
- (r, t1);
392
- };
393
-
394
- func getRec<X, Y>(x : X, compare : (X, X) -> O.Order, t : Tree<X, Y>) : ?Y {
395
- switch t {
396
- case (#leaf) { null };
397
- case (#node(c, l, xy, r)) {
398
- switch (compare(x, xy.0)) {
399
- case (#less) { getRec(x, compare, l) };
400
- case (#equal) { xy.1 };
401
- case (#greater) { getRec(x, compare, r) }
402
- }
403
- }
404
- }
405
- };
406
-
407
- /// Determine the size of the tree as the number of key-value entries.
408
- ///
409
- /// Example:
410
- /// ```motoko
411
- /// import RBTree "mo:base/RBTree";
412
- /// import Nat "mo:base/Nat";
413
- ///
414
- /// let tree = RBTree.RBTree<Nat, Text>(Nat.compare);
415
- /// tree.put(1, "one");
416
- /// tree.put(2, "two");
417
- /// tree.put(3, "three");
418
- ///
419
- /// RBTree.size(tree.share()) // 3 entries
420
- /// ```
421
- ///
422
- /// Runtime: `O(log(n))`.
423
- /// Space: `O(1)` retained memory plus garbage, see the note below.
424
- /// where `n` denotes the number of key-value entries stored in the tree.
425
- ///
426
- /// Note: Creates `O(log(n))` temporary objects that will be collected as garbage.
427
- public func size<X, Y>(t : Tree<X, Y>) : Nat {
428
- switch t {
429
- case (#leaf) { 0 };
430
- case (#node(_, l, xy, r)) {
431
- size(l) + size(r) + (switch (xy.1) { case null 0; case _ 1 })
432
- }
433
- }
434
- };
435
-
436
- func redden<X, Y>(t : Tree<X, Y>) : Tree<X, Y> {
437
- switch t {
438
- case (#node (#B, l, xy, r)) {
439
- (#node (#R, l, xy, r))
440
- };
441
- case _ {
442
- Debug.trap "RBTree.red"
443
- }
444
- }
445
- };
446
-
447
- func lbalance<X,Y>(left : Tree<X, Y>, xy : (X,?Y), right : Tree<X, Y>) : Tree<X,Y> {
448
- switch (left, right) {
449
- case (#node(#R, #node(#R, l1, xy1, r1), xy2, r2), r) {
450
- #node(
451
- #R,
452
- #node(#B, l1, xy1, r1),
453
- xy2,
454
- #node(#B, r2, xy, r))
455
- };
456
- case (#node(#R, l1, xy1, #node(#R, l2, xy2, r2)), r) {
457
- #node(
458
- #R,
459
- #node(#B, l1, xy1, l2),
460
- xy2,
461
- #node(#B, r2, xy, r))
462
- };
463
- case _ {
464
- #node(#B, left, xy, right)
465
- }
466
- }
467
- };
468
-
469
- func rbalance<X,Y>(left : Tree<X, Y>, xy : (X,?Y), right : Tree<X, Y>) : Tree<X,Y> {
470
- switch (left, right) {
471
- case (l, #node(#R, l1, xy1, #node(#R, l2, xy2, r2))) {
472
- #node(
473
- #R,
474
- #node(#B, l, xy, l1),
475
- xy1,
476
- #node(#B, l2, xy2, r2))
477
- };
478
- case (l, #node(#R, #node(#R, l1, xy1, r1), xy2, r2)) {
479
- #node(
480
- #R,
481
- #node(#B, l, xy, l1),
482
- xy1,
483
- #node(#B, r1, xy2, r2))
484
- };
485
- case _ {
486
- #node(#B, left, xy, right)
487
- };
488
- }
489
- };
490
-
491
- func insert<X, Y>(
492
- tree : Tree<X, Y>,
493
- compare : (X, X) -> O.Order,
494
- x : X,
495
- y : Y
496
- )
497
- : (Tree<X,Y>, ?Y) {
498
- var y0 : ?Y = null;
499
- func ins(tree : Tree<X,Y>) : Tree<X,Y> {
500
- switch tree {
501
- case (#leaf) {
502
- #node(#R, #leaf, (x,?y), #leaf)
503
- };
504
- case (#node(#B, left, xy, right)) {
505
- switch (compare (x, xy.0)) {
506
- case (#less) {
507
- lbalance(ins left, xy, right)
508
- };
509
- case (#greater) {
510
- rbalance(left, xy, ins right)
511
- };
512
- case (#equal) {
513
- y0 := xy.1;
514
- #node(#B, left, (x,?y), right)
515
- }
516
- }
517
- };
518
- case (#node(#R, left, xy, right)) {
519
- switch (compare (x, xy.0)) {
520
- case (#less) {
521
- #node(#R, ins left, xy, right)
522
- };
523
- case (#greater) {
524
- #node(#R, left, xy, ins right)
525
- };
526
- case (#equal) {
527
- y0 := xy.1;
528
- #node(#R, left, (x,?y), right)
529
- }
530
- }
531
- }
532
- };
533
- };
534
- switch (ins tree) {
535
- case (#node(#R, left, xy, right)) {
536
- (#node(#B, left, xy, right), y0);
537
- };
538
- case other { (other, y0) };
539
- };
540
- };
541
-
542
-
543
- func balLeft<X,Y>(left : Tree<X, Y>, xy : (X,?Y), right : Tree<X, Y>) : Tree<X,Y> {
544
- switch (left, right) {
545
- case (#node(#R, l1, xy1, r1), r) {
546
- #node(
547
- #R,
548
- #node(#B, l1, xy1, r1),
549
- xy,
550
- r)
551
- };
552
- case (_, #node(#B, l2, xy2, r2)) {
553
- rbalance(left, xy, #node(#R, l2, xy2, r2))
554
- };
555
- case (_, #node(#R, #node(#B, l2, xy2, r2), xy3, r3)) {
556
- #node(#R,
557
- #node(#B, left, xy, l2),
558
- xy2,
559
- rbalance(r2, xy3, redden r3))
560
- };
561
- case _ { Debug.trap "balLeft" };
562
- }
563
- };
564
-
565
- func balRight<X,Y>(left : Tree<X, Y>, xy : (X,?Y), right : Tree<X, Y>) : Tree<X,Y> {
566
- switch (left, right) {
567
- case (l, #node(#R, l1, xy1, r1)) {
568
- #node(#R,
569
- l,
570
- xy,
571
- #node(#B, l1, xy1, r1))
572
- };
573
- case (#node(#B, l1, xy1, r1), r) {
574
- lbalance(#node(#R, l1, xy1, r1), xy, r);
575
- };
576
- case (#node(#R, l1, xy1, #node(#B, l2, xy2, r2)), r3) {
577
- #node(#R,
578
- lbalance(redden l1, xy1, l2),
579
- xy2,
580
- #node(#B, r2, xy, r3))
581
- };
582
- case _ { Debug.trap "balRight" };
583
- }
584
- };
585
-
586
- func append<X,Y>(left : Tree<X, Y>, right: Tree<X, Y>) : Tree<X, Y> {
587
- switch (left, right) {
588
- case (#leaf, _) { right };
589
- case (_, #leaf) { left };
590
- case (#node (#R, l1, xy1, r1),
591
- #node (#R, l2, xy2, r2)) {
592
- switch (append (r1, l2)) {
593
- case (#node (#R, l3, xy3, r3)) {
594
- #node(
595
- #R,
596
- #node(#R, l1, xy1, l3),
597
- xy3,
598
- #node(#R, r3, xy2, r2))
599
- };
600
- case r1l2 {
601
- #node(#R, l1, xy1, #node(#R, r1l2, xy2, r2))
602
- }
603
- }
604
- };
605
- case (t1, #node(#R, l2, xy2, r2)) {
606
- #node(#R, append(t1, l2), xy2, r2)
607
- };
608
- case (#node(#R, l1, xy1, r1), t2) {
609
- #node(#R, l1, xy1, append(r1, t2))
610
- };
611
- case (#node(#B, l1, xy1, r1), #node (#B, l2, xy2, r2)) {
612
- switch (append (r1, l2)) {
613
- case (#node (#R, l3, xy3, r3)) {
614
- #node(#R,
615
- #node(#B, l1, xy1, l3),
616
- xy3,
617
- #node(#B, r3, xy2, r2))
618
- };
619
- case r1l2 {
620
- balLeft (
621
- l1,
622
- xy1,
623
- #node(#B, r1l2, xy2, r2)
624
- )
625
- }
626
- }
627
- }
628
- }
629
- };
630
-
631
- func remove<X, Y>(tree : Tree<X, Y>, compare : (X, X) -> O.Order, x : X) : (Tree<X,Y>, ?Y) {
632
- var y0 : ?Y = null;
633
- func delNode(left : Tree<X,Y>, xy : (X, ?Y), right : Tree<X,Y>) : Tree<X,Y> {
634
- switch (compare (x, xy.0)) {
635
- case (#less) {
636
- let newLeft = del left;
637
- switch left {
638
- case (#node(#B, _, _, _)) {
639
- balLeft(newLeft, xy, right)
640
- };
641
- case _ {
642
- #node(#R, newLeft, xy, right)
643
- }
644
- }
645
- };
646
- case (#greater) {
647
- let newRight = del right;
648
- switch right {
649
- case (#node(#B, _, _, _)) {
650
- balRight(left, xy, newRight)
651
- };
652
- case _ {
653
- #node(#R, left, xy, newRight)
654
- }
655
- }
656
- };
657
- case (#equal) {
658
- y0 := xy.1;
659
- append(left, right)
660
- };
661
- }
662
- };
663
- func del(tree : Tree<X,Y>) : Tree<X,Y> {
664
- switch tree {
665
- case (#leaf) {
666
- tree
667
- };
668
- case (#node(_, left, xy, right)) {
669
- delNode(left, xy, right)
670
- }
671
- };
672
- };
673
- switch (del(tree)) {
674
- case (#node(#R, left, xy, right)) {
675
- (#node(#B, left, xy, right), y0);
676
- };
677
- case other { (other, y0) };
678
- };
679
- }
680
-
681
- }