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.
- package/.mops/base@0.7.4/LICENSE +208 -0
- package/.mops/base@0.7.4/README.md +64 -0
- package/.mops/base@0.7.4/mops.toml +5 -0
- package/.mops/base@0.7.4/src/Array.mo +686 -0
- package/.mops/base@0.7.4/src/AssocList.mo +203 -0
- package/.mops/base@0.7.4/src/Blob.mo +55 -0
- package/.mops/base@0.7.4/src/Bool.mo +44 -0
- package/.mops/base@0.7.4/src/Buffer.mo +1937 -0
- package/.mops/base@0.7.4/src/CertifiedData.mo +29 -0
- package/.mops/base@0.7.4/src/Char.mo +67 -0
- package/.mops/base@0.7.4/src/Debug.mo +15 -0
- package/.mops/base@0.7.4/src/Deque.mo +75 -0
- package/.mops/base@0.7.4/src/Error.mo +41 -0
- package/.mops/base@0.7.4/src/ExperimentalCycles.mo +51 -0
- package/.mops/base@0.7.4/src/ExperimentalInternetComputer.mo +36 -0
- package/.mops/base@0.7.4/src/ExperimentalStableMemory.mo +121 -0
- package/.mops/base@0.7.4/src/Float.mo +150 -0
- package/.mops/base@0.7.4/src/Func.mo +38 -0
- package/.mops/base@0.7.4/src/Hash.mo +83 -0
- package/.mops/base@0.7.4/src/HashMap.mo +229 -0
- package/.mops/base@0.7.4/src/Heap.mo +113 -0
- package/.mops/base@0.7.4/src/Int.mo +150 -0
- package/.mops/base@0.7.4/src/Int16.mo +159 -0
- package/.mops/base@0.7.4/src/Int32.mo +160 -0
- package/.mops/base@0.7.4/src/Int64.mo +161 -0
- package/.mops/base@0.7.4/src/Int8.mo +160 -0
- package/.mops/base@0.7.4/src/Iter.mo +220 -0
- package/.mops/base@0.7.4/src/IterType.mo +7 -0
- package/.mops/base@0.7.4/src/List.mo +433 -0
- package/.mops/base@0.7.4/src/Nat.mo +75 -0
- package/.mops/base@0.7.4/src/Nat16.mo +146 -0
- package/.mops/base@0.7.4/src/Nat32.mo +146 -0
- package/.mops/base@0.7.4/src/Nat64.mo +146 -0
- package/.mops/base@0.7.4/src/Nat8.mo +146 -0
- package/.mops/base@0.7.4/src/None.mo +19 -0
- package/.mops/base@0.7.4/src/Option.mo +160 -0
- package/.mops/base@0.7.4/src/Order.mo +46 -0
- package/.mops/base@0.7.4/src/Prelude.mo +33 -0
- package/.mops/base@0.7.4/src/Principal.mo +58 -0
- package/.mops/base@0.7.4/src/RBTree.mo +218 -0
- package/.mops/base@0.7.4/src/Random.mo +188 -0
- package/.mops/base@0.7.4/src/Result.mo +210 -0
- package/.mops/base@0.7.4/src/Stack.mo +40 -0
- package/.mops/base@0.7.4/src/Text.mo +615 -0
- package/.mops/base@0.7.4/src/Time.mo +37 -0
- package/.mops/base@0.7.4/src/Trie.mo +1200 -0
- package/.mops/base@0.7.4/src/TrieMap.mo +180 -0
- package/.mops/base@0.7.4/src/TrieSet.mo +97 -0
- package/.mops/base@0.8.3/LICENSE +208 -0
- package/.mops/base@0.8.3/README.md +64 -0
- package/.mops/base@0.8.3/mops.toml +6 -0
- package/.mops/base@0.8.3/src/Array.mo +717 -0
- package/.mops/base@0.8.3/src/AssocList.mo +404 -0
- package/.mops/base@0.8.3/src/Blob.mo +212 -0
- package/.mops/base@0.8.3/src/Bool.mo +44 -0
- package/.mops/base@0.8.3/src/Buffer.mo +2660 -0
- package/.mops/base@0.8.3/src/CertifiedData.mo +53 -0
- package/.mops/base@0.8.3/src/Char.mo +65 -0
- package/.mops/base@0.8.3/src/Debug.mo +56 -0
- package/.mops/base@0.8.3/src/Deque.mo +243 -0
- package/.mops/base@0.8.3/src/Error.mo +68 -0
- package/.mops/base@0.8.3/src/ExperimentalCycles.mo +151 -0
- package/.mops/base@0.8.3/src/ExperimentalInternetComputer.mo +60 -0
- package/.mops/base@0.8.3/src/ExperimentalStableMemory.mo +348 -0
- package/.mops/base@0.8.3/src/Float.mo +843 -0
- package/.mops/base@0.8.3/src/Func.mo +46 -0
- package/.mops/base@0.8.3/src/Hash.mo +82 -0
- package/.mops/base@0.8.3/src/HashMap.mo +457 -0
- package/.mops/base@0.8.3/src/Heap.mo +233 -0
- package/.mops/base@0.8.3/src/Int.mo +365 -0
- package/.mops/base@0.8.3/src/Int16.mo +521 -0
- package/.mops/base@0.8.3/src/Int32.mo +522 -0
- package/.mops/base@0.8.3/src/Int64.mo +522 -0
- package/.mops/base@0.8.3/src/Int8.mo +522 -0
- package/.mops/base@0.8.3/src/Iter.mo +227 -0
- package/.mops/base@0.8.3/src/IterType.mo +7 -0
- package/.mops/base@0.8.3/src/List.mo +930 -0
- package/.mops/base@0.8.3/src/Nat.mo +305 -0
- package/.mops/base@0.8.3/src/Nat16.mo +144 -0
- package/.mops/base@0.8.3/src/Nat32.mo +144 -0
- package/.mops/base@0.8.3/src/Nat64.mo +144 -0
- package/.mops/base@0.8.3/src/Nat8.mo +144 -0
- package/.mops/base@0.8.3/src/None.mo +19 -0
- package/.mops/base@0.8.3/src/Option.mo +154 -0
- package/.mops/base@0.8.3/src/Order.mo +46 -0
- package/.mops/base@0.8.3/src/Prelude.mo +33 -0
- package/.mops/base@0.8.3/src/Principal.mo +249 -0
- package/.mops/base@0.8.3/src/RBTree.mo +681 -0
- package/.mops/base@0.8.3/src/Random.mo +270 -0
- package/.mops/base@0.8.3/src/Result.mo +209 -0
- package/.mops/base@0.8.3/src/Stack.mo +93 -0
- package/.mops/base@0.8.3/src/Text.mo +761 -0
- package/.mops/base@0.8.3/src/Time.mo +36 -0
- package/.mops/base@0.8.3/src/Timer.mo +62 -0
- package/.mops/base@0.8.3/src/Trie.mo +1603 -0
- package/.mops/base@0.8.3/src/TrieMap.mo +392 -0
- package/.mops/base@0.8.3/src/TrieSet.mo +148 -0
- package/mops.js +1 -1
- package/network.txt +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/// Class `TrieMap<K, V>` provides a map from keys of type `K` to values of type `V`.
|
|
2
|
+
/// The class wraps and manipulates an underyling hash trie, found in the `Trie`
|
|
3
|
+
/// module. The trie is a binary tree in which the position of elements in the
|
|
4
|
+
/// tree are determined using the hash of the elements.
|
|
5
|
+
///
|
|
6
|
+
/// Note: The `class` `TrieMap` exposes the same interface as `HashMap`.
|
|
7
|
+
///
|
|
8
|
+
/// Creating a map:
|
|
9
|
+
/// The equality function is used to compare keys, and the hash function is used
|
|
10
|
+
/// to hash keys. See the example below.
|
|
11
|
+
///
|
|
12
|
+
/// ```motoko name=initialize
|
|
13
|
+
/// import TrieMap "mo:base/TrieMap";
|
|
14
|
+
/// import Nat "mo:base/Nat";
|
|
15
|
+
/// import Hash "mo:base/Hash";
|
|
16
|
+
/// import Iter "mo:base/Iter";
|
|
17
|
+
///
|
|
18
|
+
/// let map = TrieMap.TrieMap<Nat, Nat>(Nat.equal, Hash.hash)
|
|
19
|
+
/// ```
|
|
20
|
+
|
|
21
|
+
import T "Trie";
|
|
22
|
+
import P "Prelude";
|
|
23
|
+
import I "Iter";
|
|
24
|
+
import Hash "Hash";
|
|
25
|
+
import List "List";
|
|
26
|
+
|
|
27
|
+
module {
|
|
28
|
+
public class TrieMap<K, V>(isEq : (K, K) -> Bool, hashOf : K -> Hash.Hash) {
|
|
29
|
+
var map = T.empty<K, V>();
|
|
30
|
+
var _size : Nat = 0;
|
|
31
|
+
|
|
32
|
+
/// Returns the number of entries in the map.
|
|
33
|
+
///
|
|
34
|
+
/// Example:
|
|
35
|
+
/// ```motoko include=initialize
|
|
36
|
+
/// map.size()
|
|
37
|
+
/// ```
|
|
38
|
+
///
|
|
39
|
+
/// Runtime: O(1)
|
|
40
|
+
/// Space: O(1)
|
|
41
|
+
public func size() : Nat { _size };
|
|
42
|
+
|
|
43
|
+
/// Maps `key` to `value`, and overwrites the old entry if the key
|
|
44
|
+
/// was already present.
|
|
45
|
+
///
|
|
46
|
+
/// Example:
|
|
47
|
+
/// ```motoko include=initialize
|
|
48
|
+
/// map.put(0, 10);
|
|
49
|
+
/// map.put(2, 12);
|
|
50
|
+
/// Iter.toArray(map.entries())
|
|
51
|
+
/// ```
|
|
52
|
+
///
|
|
53
|
+
/// Runtime: O(log(size))
|
|
54
|
+
/// Space: O(log(size))
|
|
55
|
+
///
|
|
56
|
+
/// *Runtime and space assumes that the trie is reasonably balanced and the
|
|
57
|
+
/// map is using a constant time and space equality and hash function.
|
|
58
|
+
public func put(key : K, value : V) = ignore replace(key, value);
|
|
59
|
+
|
|
60
|
+
/// Maps `key` to `value`. Overwrites _and_ returns the old entry as an
|
|
61
|
+
/// option if the key was already present, and `null` otherwise.
|
|
62
|
+
///
|
|
63
|
+
/// Example:
|
|
64
|
+
/// ```motoko include=initialize
|
|
65
|
+
/// map.put(0, 10);
|
|
66
|
+
/// map.replace(0, 20)
|
|
67
|
+
/// ```
|
|
68
|
+
///
|
|
69
|
+
/// Runtime: O(log(size))
|
|
70
|
+
/// Space: O(log(size))
|
|
71
|
+
///
|
|
72
|
+
/// *Runtime and space assumes that the trie is reasonably balanced and the
|
|
73
|
+
/// map is using a constant time and space equality and hash function.
|
|
74
|
+
public func replace(key : K, value : V) : ?V {
|
|
75
|
+
let keyObj = { key; hash = hashOf(key) };
|
|
76
|
+
let (map2, ov) = T.put<K, V>(map, keyObj, isEq, value);
|
|
77
|
+
map := map2;
|
|
78
|
+
switch (ov) {
|
|
79
|
+
case null { _size += 1 };
|
|
80
|
+
case _ {}
|
|
81
|
+
};
|
|
82
|
+
ov
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/// Gets the value associated with the key `key` in an option, or `null` if it
|
|
86
|
+
/// doesn't exist.
|
|
87
|
+
///
|
|
88
|
+
/// Example:
|
|
89
|
+
/// ```motoko include=initialize
|
|
90
|
+
/// map.put(0, 10);
|
|
91
|
+
/// map.get(0)
|
|
92
|
+
/// ```
|
|
93
|
+
///
|
|
94
|
+
/// Runtime: O(log(size))
|
|
95
|
+
/// Space: O(log(size))
|
|
96
|
+
///
|
|
97
|
+
/// *Runtime and space assumes that the trie is reasonably balanced and the
|
|
98
|
+
/// map is using a constant time and space equality and hash function.
|
|
99
|
+
public func get(key : K) : ?V {
|
|
100
|
+
let keyObj = { key; hash = hashOf(key) };
|
|
101
|
+
T.find<K, V>(map, keyObj, isEq)
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/// Delete the entry associated with key `key`, if it exists. If the key is
|
|
105
|
+
/// absent, there is no effect.
|
|
106
|
+
///
|
|
107
|
+
/// Example:
|
|
108
|
+
/// ```motoko include=initialize
|
|
109
|
+
/// map.put(0, 10);
|
|
110
|
+
/// map.delete(0);
|
|
111
|
+
/// map.get(0)
|
|
112
|
+
/// ```
|
|
113
|
+
///
|
|
114
|
+
/// Runtime: O(log(size))
|
|
115
|
+
/// Space: O(log(size))
|
|
116
|
+
///
|
|
117
|
+
/// *Runtime and space assumes that the trie is reasonably balanced and the
|
|
118
|
+
/// map is using a constant time and space equality and hash function.
|
|
119
|
+
public func delete(key : K) = ignore remove(key);
|
|
120
|
+
|
|
121
|
+
/// Delete the entry associated with key `key`. Return the deleted value
|
|
122
|
+
/// as an option if it exists, and `null` otherwise.
|
|
123
|
+
///
|
|
124
|
+
/// Example:
|
|
125
|
+
/// ```motoko include=initialize
|
|
126
|
+
/// map.put(0, 10);
|
|
127
|
+
/// map.remove(0)
|
|
128
|
+
/// ```
|
|
129
|
+
///
|
|
130
|
+
/// Runtime: O(log(size))
|
|
131
|
+
/// Space: O(log(size))
|
|
132
|
+
///
|
|
133
|
+
/// *Runtime and space assumes that the trie is reasonably balanced and the
|
|
134
|
+
/// map is using a constant time and space equality and hash function.
|
|
135
|
+
public func remove(key : K) : ?V {
|
|
136
|
+
let keyObj = { key; hash = hashOf(key) };
|
|
137
|
+
let (t, ov) = T.remove<K, V>(map, keyObj, isEq);
|
|
138
|
+
map := t;
|
|
139
|
+
switch (ov) {
|
|
140
|
+
case null {};
|
|
141
|
+
case (?_) { _size -= 1 }
|
|
142
|
+
};
|
|
143
|
+
ov
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/// Returns an iterator over the keys of the map.
|
|
147
|
+
///
|
|
148
|
+
/// Each iterator gets a _snapshot view_ of the mapping, and is unaffected
|
|
149
|
+
/// by concurrent updates to the iterated map.
|
|
150
|
+
///
|
|
151
|
+
/// Example:
|
|
152
|
+
/// ```motoko include=initialize
|
|
153
|
+
/// map.put(0, 10);
|
|
154
|
+
/// map.put(1, 11);
|
|
155
|
+
/// map.put(2, 12);
|
|
156
|
+
///
|
|
157
|
+
/// // find the sum of all the keys
|
|
158
|
+
/// var sum = 0;
|
|
159
|
+
/// for (key in map.keys()) {
|
|
160
|
+
/// sum += key;
|
|
161
|
+
/// };
|
|
162
|
+
/// // 0 + 1 + 2
|
|
163
|
+
/// sum
|
|
164
|
+
/// ```
|
|
165
|
+
///
|
|
166
|
+
/// Runtime: O(1)
|
|
167
|
+
/// Space: O(1)
|
|
168
|
+
///
|
|
169
|
+
/// *The above runtime and space are for the construction of the iterator.
|
|
170
|
+
/// The iteration itself takes linear time and logarithmic space to execute.
|
|
171
|
+
public func keys() : I.Iter<K> {
|
|
172
|
+
I.map(entries(), func(kv : (K, V)) : K { kv.0 })
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
/// Returns an iterator over the values in the map.
|
|
176
|
+
///
|
|
177
|
+
/// Each iterator gets a _snapshot view_ of the mapping, and is unaffected
|
|
178
|
+
/// by concurrent updates to the iterated map.
|
|
179
|
+
///
|
|
180
|
+
/// Example:
|
|
181
|
+
/// ```motoko include=initialize
|
|
182
|
+
/// map.put(0, 10);
|
|
183
|
+
/// map.put(1, 11);
|
|
184
|
+
/// map.put(2, 12);
|
|
185
|
+
///
|
|
186
|
+
/// // find the sum of all the values
|
|
187
|
+
/// var sum = 0;
|
|
188
|
+
/// for (key in map.vals()) {
|
|
189
|
+
/// sum += key;
|
|
190
|
+
/// };
|
|
191
|
+
/// // 10 + 11 + 12
|
|
192
|
+
/// sum
|
|
193
|
+
/// ```
|
|
194
|
+
///
|
|
195
|
+
/// Runtime: O(1)
|
|
196
|
+
/// Space: O(1)
|
|
197
|
+
///
|
|
198
|
+
/// *The above runtime and space are for the construction of the iterator.
|
|
199
|
+
/// The iteration itself takes linear time and logarithmic space to execute.
|
|
200
|
+
public func vals() : I.Iter<V> {
|
|
201
|
+
I.map(entries(), func(kv : (K, V)) : V { kv.1 })
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
/// Returns an iterator over the entries (key-value pairs) in the map.
|
|
205
|
+
///
|
|
206
|
+
/// Each iterator gets a _snapshot view_ of the mapping, and is unaffected
|
|
207
|
+
/// by concurrent updates to the iterated map.
|
|
208
|
+
///
|
|
209
|
+
/// Example:
|
|
210
|
+
/// ```motoko include=initialize
|
|
211
|
+
/// map.put(0, 10);
|
|
212
|
+
/// map.put(1, 11);
|
|
213
|
+
/// map.put(2, 12);
|
|
214
|
+
///
|
|
215
|
+
/// // find the sum of all the products of key-value pairs
|
|
216
|
+
/// var sum = 0;
|
|
217
|
+
/// for ((key, value) in map.entries()) {
|
|
218
|
+
/// sum += key * value;
|
|
219
|
+
/// };
|
|
220
|
+
/// // (0 * 10) + (1 * 11) + (2 * 12)
|
|
221
|
+
/// sum
|
|
222
|
+
/// ```
|
|
223
|
+
///
|
|
224
|
+
/// Runtime: O(1)
|
|
225
|
+
/// Space: O(1)
|
|
226
|
+
///
|
|
227
|
+
/// *The above runtime and space are for the construction of the iterator.
|
|
228
|
+
/// The iteration itself takes linear time and logarithmic space to execute.
|
|
229
|
+
public func entries() : I.Iter<(K, V)> {
|
|
230
|
+
object {
|
|
231
|
+
var stack = ?(map, null) : List.List<T.Trie<K, V>>;
|
|
232
|
+
public func next() : ?(K, V) {
|
|
233
|
+
switch stack {
|
|
234
|
+
case null { null };
|
|
235
|
+
case (?(trie, stack2)) {
|
|
236
|
+
switch trie {
|
|
237
|
+
case (#empty) {
|
|
238
|
+
stack := stack2;
|
|
239
|
+
next()
|
|
240
|
+
};
|
|
241
|
+
case (#leaf({ keyvals = null })) {
|
|
242
|
+
stack := stack2;
|
|
243
|
+
next()
|
|
244
|
+
};
|
|
245
|
+
case (#leaf({ size = c; keyvals = ?((k, v), kvs) })) {
|
|
246
|
+
stack := ?(#leaf({ size = c -1; keyvals = kvs }), stack2);
|
|
247
|
+
?(k.key, v)
|
|
248
|
+
};
|
|
249
|
+
case (#branch(br)) {
|
|
250
|
+
stack := ?(br.left, ?(br.right, stack2));
|
|
251
|
+
next()
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
/// Produce a copy of `map`, using `keyEq` to compare keys and `keyHash` to
|
|
262
|
+
/// hash keys.
|
|
263
|
+
///
|
|
264
|
+
/// Example:
|
|
265
|
+
/// ```motoko include=initialize
|
|
266
|
+
/// map.put(0, 10);
|
|
267
|
+
/// map.put(1, 11);
|
|
268
|
+
/// map.put(2, 12);
|
|
269
|
+
/// // Clone using the same equality and hash functions used to initialize `map`
|
|
270
|
+
/// let mapCopy = TrieMap.clone(map, Nat.equal, Hash.hash);
|
|
271
|
+
/// Iter.toArray(mapCopy.entries())
|
|
272
|
+
/// ```
|
|
273
|
+
///
|
|
274
|
+
/// Runtime: O(size * log(size))
|
|
275
|
+
/// Space: O(size)
|
|
276
|
+
///
|
|
277
|
+
/// *Runtime and space assumes that the trie underlying `map` is reasonably
|
|
278
|
+
/// balanced and that `keyEq` and `keyHash` run in O(1) time and space.
|
|
279
|
+
public func clone<K, V>(
|
|
280
|
+
map : TrieMap<K, V>,
|
|
281
|
+
keyEq : (K, K) -> Bool,
|
|
282
|
+
keyHash : K -> Hash.Hash
|
|
283
|
+
) : TrieMap<K, V> {
|
|
284
|
+
let h2 = TrieMap<K, V>(keyEq, keyHash);
|
|
285
|
+
for ((k, v) in map.entries()) {
|
|
286
|
+
h2.put(k, v)
|
|
287
|
+
};
|
|
288
|
+
h2
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
/// Create a new map from the entries in `entries`, using `keyEq` to compare
|
|
292
|
+
/// keys and `keyHash` to hash keys.
|
|
293
|
+
///
|
|
294
|
+
/// Example:
|
|
295
|
+
/// ```motoko include=initialize
|
|
296
|
+
/// let entries = [(0, 10), (1, 11), (2, 12)];
|
|
297
|
+
/// let newMap = TrieMap.fromEntries<Nat, Nat>(entries.vals(), Nat.equal, Hash.hash);
|
|
298
|
+
/// newMap.get(2)
|
|
299
|
+
/// ```
|
|
300
|
+
///
|
|
301
|
+
/// Runtime: O(size * log(size))
|
|
302
|
+
/// Space: O(size)
|
|
303
|
+
///
|
|
304
|
+
/// *Runtime and space assumes that `entries` returns elements in O(1) time,
|
|
305
|
+
/// and `keyEq` and `keyHash` run in O(1) time and space.
|
|
306
|
+
public func fromEntries<K, V>(
|
|
307
|
+
entries : I.Iter<(K, V)>,
|
|
308
|
+
keyEq : (K, K) -> Bool,
|
|
309
|
+
keyHash : K -> Hash.Hash
|
|
310
|
+
) : TrieMap<K, V> {
|
|
311
|
+
let h = TrieMap<K, V>(keyEq, keyHash);
|
|
312
|
+
for ((k, v) in entries) {
|
|
313
|
+
h.put(k, v)
|
|
314
|
+
};
|
|
315
|
+
h
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
/// Transform (map) the values in `map` using function `f`, retaining the keys.
|
|
319
|
+
/// Uses `keyEq` to compare keys and `keyHash` to hash keys.
|
|
320
|
+
///
|
|
321
|
+
/// Example:
|
|
322
|
+
/// ```motoko include=initialize
|
|
323
|
+
/// map.put(0, 10);
|
|
324
|
+
/// map.put(1, 11);
|
|
325
|
+
/// map.put(2, 12);
|
|
326
|
+
/// // double all the values in map
|
|
327
|
+
/// let newMap = TrieMap.map<Nat, Nat, Nat>(map, Nat.equal, Hash.hash, func(key, value) = value * 2);
|
|
328
|
+
/// Iter.toArray(newMap.entries())
|
|
329
|
+
/// ```
|
|
330
|
+
///
|
|
331
|
+
/// Runtime: O(size * log(size))
|
|
332
|
+
/// Space: O(size)
|
|
333
|
+
///
|
|
334
|
+
/// *Runtime and space assumes that `f`, `keyEq`, and `keyHash` run in O(1)
|
|
335
|
+
/// time and space.
|
|
336
|
+
public func map<K, V1, V2>(
|
|
337
|
+
map : TrieMap<K, V1>,
|
|
338
|
+
keyEq : (K, K) -> Bool,
|
|
339
|
+
keyHash : K -> Hash.Hash,
|
|
340
|
+
f : (K, V1) -> V2
|
|
341
|
+
) : TrieMap<K, V2> {
|
|
342
|
+
let h2 = TrieMap<K, V2>(keyEq, keyHash);
|
|
343
|
+
for ((k, v1) in map.entries()) {
|
|
344
|
+
let v2 = f(k, v1);
|
|
345
|
+
h2.put(k, v2)
|
|
346
|
+
};
|
|
347
|
+
h2
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
/// Transform (map) the values in `map` using function `f`, discarding entries
|
|
351
|
+
/// for which `f` evaluates to `null`. Uses `keyEq` to compare keys and
|
|
352
|
+
/// `keyHash` to hash keys.
|
|
353
|
+
///
|
|
354
|
+
/// Example:
|
|
355
|
+
/// ```motoko include=initialize
|
|
356
|
+
/// map.put(0, 10);
|
|
357
|
+
/// map.put(1, 11);
|
|
358
|
+
/// map.put(2, 12);
|
|
359
|
+
/// // double all the values in map, only keeping entries that have an even key
|
|
360
|
+
/// let newMap =
|
|
361
|
+
/// TrieMap.mapFilter<Nat, Nat, Nat>(
|
|
362
|
+
/// map,
|
|
363
|
+
/// Nat.equal,
|
|
364
|
+
/// Hash.hash,
|
|
365
|
+
/// func(key, value) = if (key % 2 == 0) { ?(value * 2) } else { null }
|
|
366
|
+
/// );
|
|
367
|
+
/// Iter.toArray(newMap.entries())
|
|
368
|
+
/// ```
|
|
369
|
+
///
|
|
370
|
+
/// Runtime: O(size * log(size))
|
|
371
|
+
/// Space: O(size)
|
|
372
|
+
///
|
|
373
|
+
/// *Runtime and space assumes that `f`, `keyEq`, and `keyHash` run in O(1)
|
|
374
|
+
/// time and space.
|
|
375
|
+
public func mapFilter<K, V1, V2>(
|
|
376
|
+
map : TrieMap<K, V1>,
|
|
377
|
+
keyEq : (K, K) -> Bool,
|
|
378
|
+
keyHash : K -> Hash.Hash,
|
|
379
|
+
f : (K, V1) -> ?V2
|
|
380
|
+
) : TrieMap<K, V2> {
|
|
381
|
+
let h2 = TrieMap<K, V2>(keyEq, keyHash);
|
|
382
|
+
for ((k, v1) in map.entries()) {
|
|
383
|
+
switch (f(k, v1)) {
|
|
384
|
+
case null {};
|
|
385
|
+
case (?v2) {
|
|
386
|
+
h2.put(k, v2)
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
h2
|
|
391
|
+
}
|
|
392
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/// Functional set
|
|
2
|
+
///
|
|
3
|
+
/// Sets are partial maps from element type to unit type,
|
|
4
|
+
/// i.e., the partial map represents the set with its domain.
|
|
5
|
+
|
|
6
|
+
// TODO-Matthew:
|
|
7
|
+
// ---------------
|
|
8
|
+
//
|
|
9
|
+
// - for now, we pass a hash value each time we pass an element value;
|
|
10
|
+
// in the future, we might avoid passing element hashes with each element in the API;
|
|
11
|
+
// related to: https://dfinity.atlassian.net/browse/AST-32
|
|
12
|
+
//
|
|
13
|
+
// - similarly, we pass an equality function when we do some operations.
|
|
14
|
+
// in the future, we might avoid this via https://dfinity.atlassian.net/browse/AST-32
|
|
15
|
+
import Trie "Trie";
|
|
16
|
+
import Hash "Hash";
|
|
17
|
+
import List "List";
|
|
18
|
+
import Iter "Iter";
|
|
19
|
+
|
|
20
|
+
module {
|
|
21
|
+
|
|
22
|
+
public type Hash = Hash.Hash;
|
|
23
|
+
public type Set<T> = Trie.Trie<T, ()>;
|
|
24
|
+
type Key<K> = Trie.Key<K>;
|
|
25
|
+
type Trie<K, V> = Trie.Trie<K, V>;
|
|
26
|
+
|
|
27
|
+
// helper for defining equal and sub, avoiding Trie.diff.
|
|
28
|
+
// TODO: add to Trie.mo?
|
|
29
|
+
private func keys<K>(t : Trie<K, Any>) : Iter.Iter<Key<K>> {
|
|
30
|
+
object {
|
|
31
|
+
var stack = ?(t, null) : List.List<Trie<K, Any>>;
|
|
32
|
+
public func next() : ?Key<K> {
|
|
33
|
+
switch stack {
|
|
34
|
+
case null { null };
|
|
35
|
+
case (?(trie, stack2)) {
|
|
36
|
+
switch trie {
|
|
37
|
+
case (#empty) {
|
|
38
|
+
stack := stack2;
|
|
39
|
+
next()
|
|
40
|
+
};
|
|
41
|
+
case (#leaf({ keyvals = null })) {
|
|
42
|
+
stack := stack2;
|
|
43
|
+
next()
|
|
44
|
+
};
|
|
45
|
+
case (#leaf({ size = c; keyvals = ?((k, v), kvs) })) {
|
|
46
|
+
stack := ?(#leaf({ size = c - 1; keyvals = kvs }), stack2);
|
|
47
|
+
?k
|
|
48
|
+
};
|
|
49
|
+
case (#branch(br)) {
|
|
50
|
+
stack := ?(br.left, ?(br.right, stack2));
|
|
51
|
+
next()
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/// Empty set.
|
|
61
|
+
public func empty<T>() : Set<T> { Trie.empty<T, ()>() };
|
|
62
|
+
|
|
63
|
+
/// Put an element into the set.
|
|
64
|
+
public func put<T>(s : Set<T>, x : T, xh : Hash, eq : (T, T) -> Bool) : Set<T> {
|
|
65
|
+
let (s2, _) = Trie.put<T, ()>(s, { key = x; hash = xh }, eq, ());
|
|
66
|
+
s2
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/// Delete an element from the set.
|
|
70
|
+
public func delete<T>(s : Set<T>, x : T, xh : Hash, eq : (T, T) -> Bool) : Set<T> {
|
|
71
|
+
let (s2, _) = Trie.remove<T, ()>(s, { key = x; hash = xh }, eq);
|
|
72
|
+
s2
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/// Test if two sets are equal.
|
|
76
|
+
public func equal<T>(s1 : Set<T>, s2 : Set<T>, eq : (T, T) -> Bool) : Bool {
|
|
77
|
+
if (Trie.size(s1) != Trie.size(s2)) return false;
|
|
78
|
+
for (k in keys(s1)) {
|
|
79
|
+
if (Trie.find<T,()>(s2, k, eq) == null) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
return true;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/// The number of set elements, set's cardinality.
|
|
87
|
+
public func size<T>(s : Set<T>) : Nat {
|
|
88
|
+
Trie.size(s);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/// Test if `s` is the empty set.
|
|
92
|
+
public func isEmpty<T>(s : Set<T>) : Bool {
|
|
93
|
+
Trie.size(s) == 0;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/// Test if `s1` is a subset of `s2`.
|
|
97
|
+
public func isSubset<T>(s1 : Set<T>, s2 : Set<T>, eq : (T, T) -> Bool) : Bool {
|
|
98
|
+
if (Trie.size(s1) > Trie.size(s2)) return false;
|
|
99
|
+
for (k in keys(s1)) {
|
|
100
|
+
if (Trie.find<T,()>(s2, k, eq) == null) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
return true;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/// Test if a set contains a given element.
|
|
108
|
+
public func mem<T>(s : Set<T>, x : T, xh : Hash, eq : (T, T) -> Bool) : Bool {
|
|
109
|
+
switch (Trie.find<T, ()>(s, { key = x; hash = xh }, eq)) {
|
|
110
|
+
case null { false };
|
|
111
|
+
case (?_) { true }
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/// [Set union](https://en.wikipedia.org/wiki/Union_(set_theory)).
|
|
116
|
+
public func union<T>(s1 : Set<T>, s2 : Set<T>, eq : (T, T) -> Bool) : Set<T> {
|
|
117
|
+
let s3 = Trie.merge<T, ()>(s1, s2, eq);
|
|
118
|
+
s3
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/// [Set difference](https://en.wikipedia.org/wiki/Difference_(set_theory)).
|
|
122
|
+
public func diff<T>(s1 : Set<T>, s2 : Set<T>, eq : (T, T) -> Bool) : Set<T> {
|
|
123
|
+
let s3 = Trie.diff<T, (), ()>(s1, s2, eq);
|
|
124
|
+
s3
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/// [Set intersection](https://en.wikipedia.org/wiki/Intersection_(set_theory)).
|
|
128
|
+
public func intersect<T>(s1 : Set<T>, s2 : Set<T>, eq : (T, T) -> Bool) : Set<T> {
|
|
129
|
+
let noop : ((), ()) -> (()) = func(_ : (), _ : ()) : (()) = ();
|
|
130
|
+
let s3 = Trie.join<T, (), (), ()>(s1, s2, eq, noop);
|
|
131
|
+
s3
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
//// Construct a set from an array.
|
|
135
|
+
public func fromArray<T>(arr : [T], elemHash : T -> Hash, eq : (T, T) -> Bool) : Set<T> {
|
|
136
|
+
var s = empty<T>();
|
|
137
|
+
for (elem in arr.vals()) {
|
|
138
|
+
s := put<T>(s, elem, elemHash(elem), eq)
|
|
139
|
+
};
|
|
140
|
+
s
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
//// Returns the set as an array.
|
|
144
|
+
public func toArray<T>(s : Set<T>) : [T] {
|
|
145
|
+
Trie.toArray(s, func(t : T, _ : ()) : T { t })
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
}
|
package/mops.js
CHANGED
package/network.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
local
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ic-mops",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mops": "cli.js"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"log-update": "^5.0.1",
|
|
40
40
|
"minimatch": "^5.0.1",
|
|
41
41
|
"ncp": "^2.0.0",
|
|
42
|
-
"node-fetch": "^
|
|
42
|
+
"node-fetch": "^3.3.0",
|
|
43
43
|
"pem-file": "^1.0.1",
|
|
44
44
|
"prompts": "^2.4.2"
|
|
45
45
|
}
|