ic-mops 0.8.3 → 0.8.5

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 (100) hide show
  1. package/.mops/base@0.7.4/LICENSE +208 -0
  2. package/.mops/base@0.7.4/README.md +64 -0
  3. package/.mops/base@0.7.4/mops.toml +5 -0
  4. package/.mops/base@0.7.4/src/Array.mo +686 -0
  5. package/.mops/base@0.7.4/src/AssocList.mo +203 -0
  6. package/.mops/base@0.7.4/src/Blob.mo +55 -0
  7. package/.mops/base@0.7.4/src/Bool.mo +44 -0
  8. package/.mops/base@0.7.4/src/Buffer.mo +1937 -0
  9. package/.mops/base@0.7.4/src/CertifiedData.mo +29 -0
  10. package/.mops/base@0.7.4/src/Char.mo +67 -0
  11. package/.mops/base@0.7.4/src/Debug.mo +15 -0
  12. package/.mops/base@0.7.4/src/Deque.mo +75 -0
  13. package/.mops/base@0.7.4/src/Error.mo +41 -0
  14. package/.mops/base@0.7.4/src/ExperimentalCycles.mo +51 -0
  15. package/.mops/base@0.7.4/src/ExperimentalInternetComputer.mo +36 -0
  16. package/.mops/base@0.7.4/src/ExperimentalStableMemory.mo +121 -0
  17. package/.mops/base@0.7.4/src/Float.mo +150 -0
  18. package/.mops/base@0.7.4/src/Func.mo +38 -0
  19. package/.mops/base@0.7.4/src/Hash.mo +83 -0
  20. package/.mops/base@0.7.4/src/HashMap.mo +229 -0
  21. package/.mops/base@0.7.4/src/Heap.mo +113 -0
  22. package/.mops/base@0.7.4/src/Int.mo +150 -0
  23. package/.mops/base@0.7.4/src/Int16.mo +159 -0
  24. package/.mops/base@0.7.4/src/Int32.mo +160 -0
  25. package/.mops/base@0.7.4/src/Int64.mo +161 -0
  26. package/.mops/base@0.7.4/src/Int8.mo +160 -0
  27. package/.mops/base@0.7.4/src/Iter.mo +220 -0
  28. package/.mops/base@0.7.4/src/IterType.mo +7 -0
  29. package/.mops/base@0.7.4/src/List.mo +433 -0
  30. package/.mops/base@0.7.4/src/Nat.mo +75 -0
  31. package/.mops/base@0.7.4/src/Nat16.mo +146 -0
  32. package/.mops/base@0.7.4/src/Nat32.mo +146 -0
  33. package/.mops/base@0.7.4/src/Nat64.mo +146 -0
  34. package/.mops/base@0.7.4/src/Nat8.mo +146 -0
  35. package/.mops/base@0.7.4/src/None.mo +19 -0
  36. package/.mops/base@0.7.4/src/Option.mo +160 -0
  37. package/.mops/base@0.7.4/src/Order.mo +46 -0
  38. package/.mops/base@0.7.4/src/Prelude.mo +33 -0
  39. package/.mops/base@0.7.4/src/Principal.mo +58 -0
  40. package/.mops/base@0.7.4/src/RBTree.mo +218 -0
  41. package/.mops/base@0.7.4/src/Random.mo +188 -0
  42. package/.mops/base@0.7.4/src/Result.mo +210 -0
  43. package/.mops/base@0.7.4/src/Stack.mo +40 -0
  44. package/.mops/base@0.7.4/src/Text.mo +615 -0
  45. package/.mops/base@0.7.4/src/Time.mo +37 -0
  46. package/.mops/base@0.7.4/src/Trie.mo +1200 -0
  47. package/.mops/base@0.7.4/src/TrieMap.mo +180 -0
  48. package/.mops/base@0.7.4/src/TrieSet.mo +97 -0
  49. package/.mops/base@0.8.3/LICENSE +208 -0
  50. package/.mops/base@0.8.3/README.md +64 -0
  51. package/.mops/base@0.8.3/mops.toml +6 -0
  52. package/.mops/base@0.8.3/src/Array.mo +717 -0
  53. package/.mops/base@0.8.3/src/AssocList.mo +404 -0
  54. package/.mops/base@0.8.3/src/Blob.mo +212 -0
  55. package/.mops/base@0.8.3/src/Bool.mo +44 -0
  56. package/.mops/base@0.8.3/src/Buffer.mo +2660 -0
  57. package/.mops/base@0.8.3/src/CertifiedData.mo +53 -0
  58. package/.mops/base@0.8.3/src/Char.mo +65 -0
  59. package/.mops/base@0.8.3/src/Debug.mo +56 -0
  60. package/.mops/base@0.8.3/src/Deque.mo +243 -0
  61. package/.mops/base@0.8.3/src/Error.mo +68 -0
  62. package/.mops/base@0.8.3/src/ExperimentalCycles.mo +151 -0
  63. package/.mops/base@0.8.3/src/ExperimentalInternetComputer.mo +60 -0
  64. package/.mops/base@0.8.3/src/ExperimentalStableMemory.mo +348 -0
  65. package/.mops/base@0.8.3/src/Float.mo +843 -0
  66. package/.mops/base@0.8.3/src/Func.mo +46 -0
  67. package/.mops/base@0.8.3/src/Hash.mo +82 -0
  68. package/.mops/base@0.8.3/src/HashMap.mo +457 -0
  69. package/.mops/base@0.8.3/src/Heap.mo +233 -0
  70. package/.mops/base@0.8.3/src/Int.mo +365 -0
  71. package/.mops/base@0.8.3/src/Int16.mo +521 -0
  72. package/.mops/base@0.8.3/src/Int32.mo +522 -0
  73. package/.mops/base@0.8.3/src/Int64.mo +522 -0
  74. package/.mops/base@0.8.3/src/Int8.mo +522 -0
  75. package/.mops/base@0.8.3/src/Iter.mo +227 -0
  76. package/.mops/base@0.8.3/src/IterType.mo +7 -0
  77. package/.mops/base@0.8.3/src/List.mo +930 -0
  78. package/.mops/base@0.8.3/src/Nat.mo +305 -0
  79. package/.mops/base@0.8.3/src/Nat16.mo +144 -0
  80. package/.mops/base@0.8.3/src/Nat32.mo +144 -0
  81. package/.mops/base@0.8.3/src/Nat64.mo +144 -0
  82. package/.mops/base@0.8.3/src/Nat8.mo +144 -0
  83. package/.mops/base@0.8.3/src/None.mo +19 -0
  84. package/.mops/base@0.8.3/src/Option.mo +154 -0
  85. package/.mops/base@0.8.3/src/Order.mo +46 -0
  86. package/.mops/base@0.8.3/src/Prelude.mo +33 -0
  87. package/.mops/base@0.8.3/src/Principal.mo +249 -0
  88. package/.mops/base@0.8.3/src/RBTree.mo +681 -0
  89. package/.mops/base@0.8.3/src/Random.mo +270 -0
  90. package/.mops/base@0.8.3/src/Result.mo +209 -0
  91. package/.mops/base@0.8.3/src/Stack.mo +93 -0
  92. package/.mops/base@0.8.3/src/Text.mo +761 -0
  93. package/.mops/base@0.8.3/src/Time.mo +36 -0
  94. package/.mops/base@0.8.3/src/Timer.mo +62 -0
  95. package/.mops/base@0.8.3/src/Trie.mo +1603 -0
  96. package/.mops/base@0.8.3/src/TrieMap.mo +392 -0
  97. package/.mops/base@0.8.3/src/TrieSet.mo +148 -0
  98. package/mops.js +1 -1
  99. package/network.txt +1 -0
  100. package/package.json +2 -2
@@ -0,0 +1,46 @@
1
+ /// Functions on functions, creating functions from simpler inputs.
2
+ ///
3
+ /// (Most commonly used when programming in functional style using higher-order
4
+ /// functions.)
5
+
6
+ module {
7
+ /// Import from the base library to use this module.
8
+ ///
9
+ /// ```motoko name=import
10
+ /// import { compose; const; identity } = "mo:base/Func";
11
+ /// import Text = "mo:base/Text";
12
+ /// import Char = "mo:base/Char";
13
+ /// ```
14
+
15
+ /// The composition of two functions `f` and `g` is a function that applies `g` and then `f`.
16
+ ///
17
+ /// Example:
18
+ /// ```motoko include=import
19
+ /// let textFromNat32 = compose(Text.fromChar, Char.fromNat32);
20
+ /// assert textFromNat32(65) == "A";
21
+ /// ```
22
+ public func compose<A, B, C>(f : B -> C, g : A -> B) : A -> C {
23
+ func(x : A) : C {
24
+ f(g(x))
25
+ }
26
+ };
27
+
28
+ /// The `identity` function returns its argument.
29
+ /// Example:
30
+ /// ```motoko include=import
31
+ /// assert identity(10) == 10;
32
+ /// assert identity(true) == true;
33
+ /// ```
34
+ public func identity<A>(x : A) : A = x;
35
+
36
+ /// The const function is a _curried_ function that accepts an argument `x`,
37
+ /// and then returns a function that discards its argument and always returns
38
+ /// the `x`.
39
+ ///
40
+ /// Example:
41
+ /// ```motoko include=import
42
+ /// assert const<Nat, Text>(10)("hello") == 10;
43
+ /// assert const(true)(20) == true;
44
+ /// ```
45
+ public func const<A, B>(x : A) : B -> A = func _ = x
46
+ }
@@ -0,0 +1,82 @@
1
+ /// Hash values
2
+
3
+ import Prim "mo:⛔";
4
+ import Iter "Iter";
5
+
6
+ module {
7
+
8
+ /// Hash values represent a string of _hash bits_, packed into a `Nat32`.
9
+ public type Hash = Nat32;
10
+
11
+ /// The hash length, always 31.
12
+ public let length : Nat = 31; // Why not 32?
13
+
14
+ /// Project a given bit from the bit vector.
15
+ public func bit(h : Hash, pos : Nat) : Bool {
16
+ assert (pos <= length);
17
+ (h & (Prim.natToNat32(1) << Prim.natToNat32(pos))) != Prim.natToNat32(0)
18
+ };
19
+
20
+ /// Test if two hashes are equal
21
+ public func equal(ha : Hash, hb : Hash) : Bool {
22
+ ha == hb
23
+ };
24
+
25
+ /// Computes a hash from the least significant 32-bits of `n`, ignoring other bits.
26
+ /// @deprecated For large `Nat` values consider using a bespoke hash function that considers all of the argument's bits.
27
+ public func hash(n : Nat) : Hash {
28
+ let j = Prim.intToNat32Wrap(n);
29
+ hashNat8([
30
+ j & (255 << 0),
31
+ j & (255 << 8),
32
+ j & (255 << 16),
33
+ j & (255 << 24)
34
+ ])
35
+ };
36
+
37
+ /// @deprecated This function will be removed in future.
38
+ public func debugPrintBits(bits : Hash) {
39
+ for (j in Iter.range(0, length - 1)) {
40
+ if (bit(bits, j)) {
41
+ Prim.debugPrint("1")
42
+ } else {
43
+ Prim.debugPrint("0")
44
+ }
45
+ }
46
+ };
47
+
48
+ /// @deprecated This function will be removed in future.
49
+ public func debugPrintBitsRev(bits : Hash) {
50
+ for (j in Iter.revRange(length - 1, 0)) {
51
+ if (bit(bits, Prim.abs(j))) {
52
+ Prim.debugPrint("1")
53
+ } else {
54
+ Prim.debugPrint("0")
55
+ }
56
+ }
57
+ };
58
+
59
+ /// Jenkin's one at a time:
60
+ ///
61
+ /// https://en.wikipedia.org/wiki/Jenkins_hash_function#one_at_a_time
62
+ ///
63
+ /// The input type should actually be `[Nat8]`.
64
+ /// Note: Be sure to explode each `Nat8` of a `Nat32` into its own `Nat32`, and to shift into lower 8 bits.
65
+
66
+ // should this really be public?
67
+ // NB: Int.mo contains a local copy of hashNat8 (redefined to suppress the deprecation warning).
68
+ /// @deprecated This function may be removed or changed in future.
69
+ public func hashNat8(key : [Hash]) : Hash {
70
+ var hash : Nat32 = 0;
71
+ for (natOfKey in key.vals()) {
72
+ hash := hash +% natOfKey;
73
+ hash := hash +% hash << 10;
74
+ hash := hash ^ (hash >> 6)
75
+ };
76
+ hash := hash +% hash << 3;
77
+ hash := hash ^ (hash >> 11);
78
+ hash := hash +% hash << 15;
79
+ return hash
80
+ };
81
+
82
+ }
@@ -0,0 +1,457 @@
1
+ /// Class `HashMap<K, V>` provides a hashmap from keys of type `K` to values of type `V`.
2
+
3
+ /// The class is parameterized by the key's equality and hash functions,
4
+ /// and an initial capacity. However, the underlying allocation happens only when
5
+ /// the first key-value entry is inserted.
6
+ ///
7
+ /// Internally, the map is represented as an array of `AssocList` (buckets).
8
+ /// The growth policy of the underyling array is very simple, for now: double
9
+ /// the current capacity when the expected bucket list size grows beyond a
10
+ /// certain constant.
11
+ ///
12
+ /// WARNING: Certain operations are amortized O(1) time, such as `put`, but run
13
+ /// in worst case O(size) time. These worst case runtimes may exceed the cycles limit
14
+ /// per message if the size of the map is large enough. Further, this runtime analysis
15
+ /// assumes that the hash functions uniformly maps keys over the hash space. Grow these structures
16
+ /// with discretion, and with good hash functions. All amortized operations
17
+ /// below also list the worst case runtime.
18
+ ///
19
+ /// For maps without amortization, see `TrieMap`.
20
+ ///
21
+ /// Note on the constructor:
22
+ /// The argument `initCapacity` determines the initial number of buckets in the
23
+ /// underyling array. Also, the runtime and space anlyses in this documentation
24
+ /// assumes that the equality and hash functions for keys used to construct the
25
+ /// map run in O(1) time and space.
26
+ ///
27
+ /// Example:
28
+ /// ```motoko name=initialize
29
+ /// import HashMap "mo:base/HashMap";
30
+ /// import Text "mo:base/Text";
31
+ ///
32
+ /// let map = HashMap.HashMap<Text, Nat>(5, Text.equal, Text.hash);
33
+ /// ```
34
+ ///
35
+ /// Runtime: O(1)
36
+ ///
37
+ /// Space: O(1)
38
+
39
+ import Prim "mo:⛔";
40
+ import P "Prelude";
41
+ import A "Array";
42
+ import Hash "Hash";
43
+ import Iter "Iter";
44
+ import AssocList "AssocList";
45
+ import Nat32 "Nat32";
46
+
47
+ module {
48
+
49
+ // hash field avoids re-hashing the key when the array grows.
50
+ type Key<K> = (Hash.Hash, K);
51
+
52
+ // key-val list type
53
+ type KVs<K, V> = AssocList.AssocList<Key<K>, V>;
54
+
55
+ public class HashMap<K, V>(
56
+ initCapacity : Nat,
57
+ keyEq : (K, K) -> Bool,
58
+ keyHash : K -> Hash.Hash
59
+ ) {
60
+
61
+ var table : [var KVs<K, V>] = [var];
62
+ var _count : Nat = 0;
63
+
64
+ /// Returns the current number of key-value entries in the map.
65
+ ///
66
+ /// Example:
67
+ /// ```motoko include=initialize
68
+ /// map.size() // => 0
69
+ /// ```
70
+ ///
71
+ /// Runtime: O(1)
72
+ ///
73
+ /// Space: O(1)
74
+ public func size() : Nat = _count;
75
+
76
+ /// Returns the value assocaited with key `key` if present and `null` otherwise.
77
+ ///
78
+ /// Example:
79
+ /// ```motoko include=initialize
80
+ /// map.put("key", 3);
81
+ /// map.get("key") // => ?3
82
+ /// ```
83
+ ///
84
+ /// Expected Runtime: O(1), Worst Case Runtime: O(size)
85
+ ///
86
+ /// Space: O(1)
87
+ public func get(key : K) : (value : ?V) {
88
+ let h = Prim.nat32ToNat(keyHash(key));
89
+ let m = table.size();
90
+ let v = if (m > 0) {
91
+ AssocList.find<Key<K>, V>(table[h % m], keyHash_(key), keyHashEq)
92
+ } else {
93
+ null
94
+ }
95
+ };
96
+
97
+ /// Insert the value `value` with key `key`. Overwrites any existing entry with key `key`.
98
+ ///
99
+ /// Example:
100
+ /// ```motoko include=initialize
101
+ /// map.put("key", 3);
102
+ /// map.get("key") // => ?3
103
+ /// ```
104
+ ///
105
+ /// Expected Amortized Runtime: O(1), Worst Case Runtime: O(size)
106
+ ///
107
+ /// Expected Amortized Space: O(1), Worst Case Space: O(size)
108
+ ///
109
+ /// Note: If this is the first entry into this map, this operation will cause
110
+ /// the initial allocation of the underlying array.
111
+ public func put(key : K, value : V) = ignore replace(key, value);
112
+
113
+ /// Insert the value `value` with key `key`. Returns the previous value
114
+ /// associated with key `key` or `null` if no such value exists.
115
+ ///
116
+ /// Example:
117
+ /// ```motoko include=initialize
118
+ /// map.put("key", 3);
119
+ /// ignore map.replace("key", 2); // => ?3
120
+ /// map.get("key") // => ?2
121
+ /// ```
122
+ ///
123
+ /// Expected Amortized Runtime: O(1), Worst Case Runtime: O(size)
124
+ ///
125
+ /// Expected Amortized Space: O(1), Worst Case Space: O(size)
126
+ ///
127
+ /// Note: If this is the first entry into this map, this operation will cause
128
+ /// the initial allocation of the underlying array.
129
+ public func replace(key : K, value : V) : (oldValue : ?V) {
130
+ if (_count >= table.size()) {
131
+ let size = if (_count == 0) {
132
+ if (initCapacity > 0) {
133
+ initCapacity
134
+ } else {
135
+ 1
136
+ }
137
+ } else {
138
+ table.size() * 2
139
+ };
140
+ let table2 = A.init<KVs<K, V>>(size, null);
141
+ for (i in table.keys()) {
142
+ var kvs = table[i];
143
+ label moveKeyVals : () loop {
144
+ switch kvs {
145
+ case null { break moveKeyVals };
146
+ case (?((k, v), kvsTail)) {
147
+ let pos2 = Nat32.toNat(k.0) % table2.size(); // critical: uses saved hash. no re-hash.
148
+ table2[pos2] := ?((k, v), table2[pos2]);
149
+ kvs := kvsTail
150
+ }
151
+ }
152
+ }
153
+ };
154
+ table := table2
155
+ };
156
+ let h = Prim.nat32ToNat(keyHash(key));
157
+ let pos = h % table.size();
158
+ let (kvs2, ov) = AssocList.replace<Key<K>, V>(table[pos], keyHash_(key), keyHashEq, ?value);
159
+ table[pos] := kvs2;
160
+ switch (ov) {
161
+ case null { _count += 1 };
162
+ case _ {}
163
+ };
164
+ ov
165
+ };
166
+
167
+ /// Deletes the entry with the key `key`. Has no effect if `key` is not
168
+ /// present in the map.
169
+ ///
170
+ /// Example:
171
+ /// ```motoko include=initialize
172
+ /// map.put("key", 3);
173
+ /// map.delete("key");
174
+ /// map.get("key"); // => null
175
+ /// ```
176
+ ///
177
+ /// Expected Runtime: O(1), Worst Case Runtime: O(size)
178
+ ///
179
+ /// Expected Space: O(1), Worst Case Space: O(size)
180
+ public func delete(key : K) = ignore remove(key);
181
+
182
+ func keyHash_(k : K) : Key<K> = (keyHash(k), k);
183
+
184
+ func keyHashEq(k1 : Key<K>, k2 : Key<K>) : Bool {
185
+ k1.0 == k2.0 and keyEq(k1.1, k2.1)
186
+ };
187
+
188
+ /// Deletes the entry with the key `key`. Returns the previous value
189
+ /// associated with key `key` or `null` if no such value exists.
190
+ ///
191
+ /// Example:
192
+ /// ```motoko include=initialize
193
+ /// map.put("key", 3);
194
+ /// map.remove("key"); // => ?3
195
+ /// ```
196
+ ///
197
+ /// Expected Runtime: O(1), Worst Case Runtime: O(size)
198
+ ///
199
+ /// Expected Space: O(1), Worst Case Space: O(size)
200
+ public func remove(key : K) : (oldValue : ?V) {
201
+ let m = table.size();
202
+ if (m > 0) {
203
+ let h = Prim.nat32ToNat(keyHash(key));
204
+ let pos = h % m;
205
+ let (kvs2, ov) = AssocList.replace<Key<K>, V>(table[pos], keyHash_(key), keyHashEq, null);
206
+ table[pos] := kvs2;
207
+ switch (ov) {
208
+ case null {};
209
+ case _ { _count -= 1 }
210
+ };
211
+ ov
212
+ } else {
213
+ null
214
+ }
215
+ };
216
+
217
+ /// Returns an Iterator (`Iter`) over the keys of the map.
218
+ /// Iterator provides a single method `next()`, which returns
219
+ /// keys in no specific order, or `null` when out of keys to iterate over.
220
+ ///
221
+ /// Example:
222
+ /// ```motoko include=initialize
223
+ ///
224
+ /// map.put("key1", 1);
225
+ /// map.put("key2", 2);
226
+ /// map.put("key3", 3);
227
+ ///
228
+ /// var keys = "";
229
+ /// for (key in map.keys()) {
230
+ /// keys := key # " " # keys
231
+ /// };
232
+ /// keys // => "key3 key2 key1 "
233
+ /// ```
234
+ ///
235
+ /// Cost of iteration over all keys:
236
+ ///
237
+ /// Runtime: O(size)
238
+ ///
239
+ /// Space: O(1)
240
+ public func keys() : Iter.Iter<K> {
241
+ Iter.map(entries(), func(kv : (K, V)) : K { kv.0 })
242
+ };
243
+
244
+ /// Returns an Iterator (`Iter`) over the values of the map.
245
+ /// Iterator provides a single method `next()`, which returns
246
+ /// values in no specific order, or `null` when out of values to iterate over.
247
+ ///
248
+ /// Example:
249
+ /// ```motoko include=initialize
250
+ ///
251
+ /// map.put("key1", 1);
252
+ /// map.put("key2", 2);
253
+ /// map.put("key3", 3);
254
+ ///
255
+ /// var sum = 0;
256
+ /// for (value in map.vals()) {
257
+ /// sum += value;
258
+ /// };
259
+ /// sum // => 6
260
+ /// ```
261
+ ///
262
+ /// Cost of iteration over all values:
263
+ ///
264
+ /// Runtime: O(size)
265
+ ///
266
+ /// Space: O(1)
267
+ public func vals() : Iter.Iter<V> {
268
+ Iter.map(entries(), func(kv : (K, V)) : V { kv.1 })
269
+ };
270
+
271
+ /// Returns an Iterator (`Iter`) over the key-value pairs in the map.
272
+ /// Iterator provides a single method `next()`, which returns
273
+ /// pairs in no specific order, or `null` when out of pairs to iterate over.
274
+ ///
275
+ /// Example:
276
+ /// ```motoko include=initialize
277
+ /// import Nat "mo:base/Nat";
278
+ ///
279
+ /// map.put("key1", 1);
280
+ /// map.put("key2", 2);
281
+ /// map.put("key3", 3);
282
+ ///
283
+ /// var pairs = "";
284
+ /// for ((key, value) in map.entries()) {
285
+ /// pairs := "(" # key # ", " # Nat.toText(value) # ") " # pairs
286
+ /// };
287
+ /// pairs // => "(key3, 3) (key2, 2) (key1, 1)"
288
+ /// ```
289
+ ///
290
+ /// Cost of iteration over all pairs:
291
+ ///
292
+ /// Runtime: O(size)
293
+ ///
294
+ /// Space: O(1)
295
+ public func entries() : Iter.Iter<(K, V)> {
296
+ if (table.size() == 0) {
297
+ object { public func next() : ?(K, V) { null } }
298
+ } else {
299
+ object {
300
+ var kvs = table[0];
301
+ var nextTablePos = 1;
302
+ public func next() : ?(K, V) {
303
+ switch kvs {
304
+ case (?(kv, kvs2)) {
305
+ kvs := kvs2;
306
+ ?(kv.0.1, kv.1)
307
+ };
308
+ case null {
309
+ if (nextTablePos < table.size()) {
310
+ kvs := table[nextTablePos];
311
+ nextTablePos += 1;
312
+ next()
313
+ } else {
314
+ null
315
+ }
316
+ }
317
+ }
318
+ }
319
+ }
320
+ }
321
+ };
322
+
323
+ };
324
+
325
+ /// Returns a copy of `map`, initializing the copy with the provided equality
326
+ /// and hash functions.
327
+ ///
328
+ /// Example:
329
+ /// ```motoko include=initialize
330
+ /// map.put("key1", 1);
331
+ /// map.put("key2", 2);
332
+ /// map.put("key3", 3);
333
+ ///
334
+ /// let map2 = HashMap.clone(map, Text.equal, Text.hash);
335
+ /// map2.get("key1") // => ?1
336
+ /// ```
337
+ ///
338
+ /// Expected Runtime: O(size), Worst Case Runtime: O(size * size)
339
+ ///
340
+ /// Expected Space: O(size), Worst Case Space: O(size)
341
+ public func clone<K, V>(
342
+ map : HashMap<K, V>,
343
+ keyEq : (K, K) -> Bool,
344
+ keyHash : K -> Hash.Hash
345
+ ) : HashMap<K, V> {
346
+ let h2 = HashMap<K, V>(map.size(), keyEq, keyHash);
347
+ for ((k, v) in map.entries()) {
348
+ h2.put(k, v)
349
+ };
350
+ h2
351
+ };
352
+
353
+ /// Returns a new map, containing all entries given by the iterator `iter`.
354
+ /// The new map is initialized with the provided initial capacity, equality,
355
+ /// and hash functions.
356
+ ///
357
+ /// Example:
358
+ /// ```motoko include=initialize
359
+ /// let entries = [("key3", 3), ("key2", 2), ("key1", 1)];
360
+ /// let iter = entries.vals();
361
+ ///
362
+ /// let map2 = HashMap.fromIter<Text, Nat>(iter, entries.size(), Text.equal, Text.hash);
363
+ /// map2.get("key1") // => ?1
364
+ /// ```
365
+ ///
366
+ /// Expected Runtime: O(size), Worst Case Runtime: O(size * size)
367
+ ///
368
+ /// Expected Space: O(size), Worst Case Space: O(size)
369
+ public func fromIter<K, V>(
370
+ iter : Iter.Iter<(K, V)>,
371
+ initCapacity : Nat,
372
+ keyEq : (K, K) -> Bool,
373
+ keyHash : K -> Hash.Hash
374
+ ) : HashMap<K, V> {
375
+ let h = HashMap<K, V>(initCapacity, keyEq, keyHash);
376
+ for ((k, v) in iter) {
377
+ h.put(k, v)
378
+ };
379
+ h
380
+ };
381
+
382
+ /// Creates a new map by applying `f` to each entry in `hashMap`. Each entry
383
+ /// `(k, v)` in the old map is transformed into a new entry `(k, v2)`, where
384
+ /// the new value `v2` is created by applying `f` to `(k, v)`.
385
+ ///
386
+ /// ```motoko include=initialize
387
+ /// map.put("key1", 1);
388
+ /// map.put("key2", 2);
389
+ /// map.put("key3", 3);
390
+ ///
391
+ /// let map2 = HashMap.map<Text, Nat, Nat>(map, Text.equal, Text.hash, func (k, v) = v * 2);
392
+ /// map2.get("key2") // => ?4
393
+ /// ```
394
+ ///
395
+ /// Expected Runtime: O(size), Worst Case Runtime: O(size * size)
396
+ ///
397
+ /// Expected Space: O(size), Worst Case Space: O(size)
398
+ ///
399
+ /// *Runtime and space assumes that `f` runs in O(1) time and space.
400
+ public func map<K, V1, V2>(
401
+ hashMap : HashMap<K, V1>,
402
+ keyEq : (K, K) -> Bool,
403
+ keyHash : K -> Hash.Hash,
404
+ f : (K, V1) -> V2
405
+ ) : HashMap<K, V2> {
406
+ let h2 = HashMap<K, V2>(hashMap.size(), keyEq, keyHash);
407
+ for ((k, v1) in hashMap.entries()) {
408
+ let v2 = f(k, v1);
409
+ h2.put(k, v2)
410
+ };
411
+ h2
412
+ };
413
+
414
+ /// Creates a new map by applying `f` to each entry in `hashMap`. For each entry
415
+ /// `(k, v)` in the old map, if `f` evaluates to `null`, the entry is discarded.
416
+ /// Otherwise, the entry is transformed into a new entry `(k, v2)`, where
417
+ /// the new value `v2` is the result of applying `f` to `(k, v)`.
418
+ ///
419
+ /// ```motoko include=initialize
420
+ /// map.put("key1", 1);
421
+ /// map.put("key2", 2);
422
+ /// map.put("key3", 3);
423
+ ///
424
+ /// let map2 =
425
+ /// HashMap.mapFilter<Text, Nat, Nat>(
426
+ /// map,
427
+ /// Text.equal,
428
+ /// Text.hash,
429
+ /// func (k, v) = if (v == 2) { null } else { ?(v * 2)}
430
+ /// );
431
+ /// map2.get("key3") // => ?6
432
+ /// ```
433
+ ///
434
+ /// Expected Runtime: O(size), Worst Case Runtime: O(size * size)
435
+ ///
436
+ /// Expected Space: O(size), Worst Case Space: O(size)
437
+ ///
438
+ /// *Runtime and space assumes that `f` runs in O(1) time and space.
439
+ public func mapFilter<K, V1, V2>(
440
+ hashMap : HashMap<K, V1>,
441
+ keyEq : (K, K) -> Bool,
442
+ keyHash : K -> Hash.Hash,
443
+ f : (K, V1) -> ?V2
444
+ ) : HashMap<K, V2> {
445
+ let h2 = HashMap<K, V2>(hashMap.size(), keyEq, keyHash);
446
+ for ((k, v1) in hashMap.entries()) {
447
+ switch (f(k, v1)) {
448
+ case null {};
449
+ case (?v2) {
450
+ h2.put(k, v2)
451
+ }
452
+ }
453
+ };
454
+ h2
455
+ };
456
+
457
+ }