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,404 @@
1
+ /// Map implemented as a linked-list of key-value pairs ("Associations").
2
+ ///
3
+ /// NOTE: This map implementation is mainly used as underlying buckets for other map
4
+ /// structures. Thus, other map implementations are easier to use in most cases.
5
+
6
+ import List "List";
7
+
8
+ module {
9
+ /// Import from the base library to use this module.
10
+ ///
11
+ /// ```motoko name=import
12
+ /// import AssocList "mo:base/AssocList";
13
+ /// import List "mo:base/List";
14
+ /// import Nat "mo:base/Nat";
15
+ ///
16
+ /// type AssocList<K, V> = AssocList.AssocList<K, V>;
17
+ /// ```
18
+ ///
19
+ /// Initialize an empty map using an empty list.
20
+ /// ```motoko name=initialize include=import
21
+ /// var map : AssocList<Nat, Nat> = List.nil(); // Empty list as an empty map
22
+ /// map := null; // Alternative: null as empty list.
23
+ /// map
24
+ /// ```
25
+ public type AssocList<K, V> = List.List<(K, V)>;
26
+
27
+ /// Find the value associated with key `key`, or `null` if no such key exists.
28
+ /// Compares keys using the provided function `equal`.
29
+ ///
30
+ /// Example:
31
+ /// ```motoko include=import,initialize
32
+ /// // Create map = [(0, 10), (1, 11), (2, 12)]
33
+ /// map := AssocList.replace(map, 0, Nat.equal, ?10).0;
34
+ /// map := AssocList.replace(map, 1, Nat.equal, ?11).0;
35
+ /// map := AssocList.replace(map, 2, Nat.equal, ?12).0;
36
+ ///
37
+ /// // Find value associated with key 1
38
+ /// AssocList.find(map, 1, Nat.equal)
39
+ /// ```
40
+ /// Runtime: O(size)
41
+ ///
42
+ /// Space: O(1)
43
+ ///
44
+ /// *Runtime and space assumes that `equal` runs in O(1) time and space.
45
+ public func find<K, V>(
46
+ map : AssocList<K, V>,
47
+ key : K,
48
+ equal : (K, K) -> Bool
49
+ ) : ?V {
50
+ func rec(al : AssocList<K, V>) : ?V {
51
+ label profile_assocList_find_rec : (?V) switch (al) {
52
+ case (null) { label profile_assocList_find_end_fail : (?V) { null } };
53
+ case (?((hd_k, hd_v), tl)) {
54
+ if (equal(key, hd_k)) {
55
+ label profile_assocList_find_end_success : (?V) {
56
+ ?hd_v
57
+ }
58
+ } else {
59
+ rec(tl)
60
+ }
61
+ }
62
+ }
63
+ };
64
+ label profile_assocList_find_begin : (?V) {
65
+ rec(map)
66
+ }
67
+ };
68
+
69
+ /// Maps `key` to `value` in `map`, and overwrites the old entry if the key
70
+ /// was already present. Returns the old value in an option if it existed and
71
+ /// `null` otherwise, as well as the new map. Compares keys using the provided
72
+ /// function `equal`.
73
+ ///
74
+ /// Example:
75
+ /// ```motoko include=import,initialize
76
+ /// // Add three entries to the map
77
+ /// // map = [(0, 10), (1, 11), (2, 12)]
78
+ /// map := AssocList.replace(map, 0, Nat.equal, ?10).0;
79
+ /// map := AssocList.replace(map, 1, Nat.equal, ?11).0;
80
+ /// map := AssocList.replace(map, 2, Nat.equal, ?12).0;
81
+ /// // Override second entry
82
+ /// map := AssocList.replace(map, 1, Nat.equal, ?21).0;
83
+ ///
84
+ /// List.toArray(map)
85
+ /// ```
86
+ /// Runtime: O(size)
87
+ ///
88
+ /// Space: O(size)
89
+ ///
90
+ /// *Runtime and space assumes that `equal` runs in O(1) time and space.
91
+ public func replace<K, V>(
92
+ map : AssocList<K, V>,
93
+ key : K,
94
+ equal : (K, K) -> Bool,
95
+ value : ?V
96
+ ) : (AssocList<K, V>, ?V) {
97
+ func rec(al : AssocList<K, V>) : (AssocList<K, V>, ?V) {
98
+ switch (al) {
99
+ case (null) {
100
+ switch value {
101
+ case (null) { (null, null) };
102
+ case (?value) { (?((key, value), null), null) }
103
+ }
104
+ };
105
+ case (?((hd_k, hd_v), tl)) {
106
+ if (equal(key, hd_k)) {
107
+ // if value is null, remove the key; otherwise, replace key's old value
108
+ // return old value
109
+ switch value {
110
+ case (null) { (tl, ?hd_v) };
111
+ case (?value) { (?((hd_k, value), tl), ?hd_v) }
112
+ }
113
+ } else {
114
+ let (tl2, old_v) = rec(tl);
115
+ (?((hd_k, hd_v), tl2), old_v)
116
+ }
117
+ }
118
+ }
119
+ };
120
+ rec(map)
121
+ };
122
+
123
+ /// Produces a new map containing all entries from `map1` whose keys are not
124
+ /// contained in `map2`. The "extra" entries in `map2` are ignored. Compares
125
+ /// keys using the provided function `equal`.
126
+ ///
127
+ /// Example:
128
+ /// ```motoko include=import,initialize
129
+ /// // Create map1 = [(0, 10), (1, 11), (2, 12)]
130
+ /// var map1 : AssocList<Nat, Nat> = null;
131
+ /// map1 := AssocList.replace(map1, 0, Nat.equal, ?10).0;
132
+ /// map1 := AssocList.replace(map1, 1, Nat.equal, ?11).0;
133
+ /// map1 := AssocList.replace(map1, 2, Nat.equal, ?12).0;
134
+ ///
135
+ /// // Create map2 = [(2, 12), (3, 13)]
136
+ /// var map2 : AssocList<Nat, Nat> = null;
137
+ /// map2 := AssocList.replace(map2, 2, Nat.equal, ?12).0;
138
+ /// map2 := AssocList.replace(map2, 3, Nat.equal, ?13).0;
139
+ ///
140
+ /// // Take the difference
141
+ /// let newMap = AssocList.diff(map1, map2, Nat.equal);
142
+ /// List.toArray(newMap)
143
+ /// ```
144
+ /// Runtime: O(size1 * size2)
145
+ ///
146
+ /// Space: O(1)
147
+ ///
148
+ /// *Runtime and space assumes that `equal` runs in O(1) time and space.
149
+ public func diff<K, V, W>(
150
+ map1 : AssocList<K, V>,
151
+ map2 : AssocList<K, W>,
152
+ equal : (K, K) -> Bool
153
+ ) : AssocList<K, V> {
154
+ func rec(al1 : AssocList<K, V>) : AssocList<K, V> {
155
+ switch al1 {
156
+ case (null) { null };
157
+ case (?((k, v1), tl)) {
158
+ switch (find<K, W>(map2, k, equal)) {
159
+ case (null) { ?((k, v1), rec(tl)) };
160
+ case (?v2) { rec(tl) }
161
+ }
162
+ }
163
+ }
164
+ };
165
+ rec(map1)
166
+ };
167
+
168
+ /// @deprecated
169
+ public func mapAppend<K, V, W, X>(
170
+ map1 : AssocList<K, V>,
171
+ map2 : AssocList<K, W>,
172
+ f : (?V, ?W) -> X
173
+ ) : AssocList<K, X> = label profile_assocList_mapAppend : AssocList<K, X> {
174
+ func rec(al1 : AssocList<K, V>, al2 : AssocList<K, W>) : AssocList<K, X> = label profile_assocList_mapAppend_rec : AssocList<K, X> {
175
+ switch (al1, al2) {
176
+ case (null, null) { null };
177
+ case (?((k, v), al1_), _) { ?((k, f(?v, null)), rec(al1_, al2)) };
178
+ case (null, ?((k, v), al2_)) { ?((k, f(null, ?v)), rec(null, al2_)) }
179
+ }
180
+ };
181
+ rec(map1, map2)
182
+ };
183
+
184
+ /// Produces a new map by mapping entries in `map1` and `map2` using `f` and
185
+ /// concatenating the results. Assumes that there are no collisions between
186
+ /// keys in `map1` and `map2`.
187
+ ///
188
+ /// Example:
189
+ /// ```motoko include=import,initialize
190
+ /// import { trap } "mo:base/Debug";
191
+ ///
192
+ /// // Create map1 = [(0, 10), (1, 11), (2, 12)]
193
+ /// var map1 : AssocList<Nat, Nat> = null;
194
+ /// map1 := AssocList.replace(map1, 0, Nat.equal, ?10).0;
195
+ /// map1 := AssocList.replace(map1, 1, Nat.equal, ?11).0;
196
+ /// map1 := AssocList.replace(map1, 2, Nat.equal, ?12).0;
197
+ ///
198
+ /// // Create map2 = [(4, "14"), (3, "13")]
199
+ /// var map2 : AssocList<Nat, Text> = null;
200
+ /// map2 := AssocList.replace(map2, 4, Nat.equal, ?"14").0;
201
+ /// map2 := AssocList.replace(map2, 3, Nat.equal, ?"13").0;
202
+ ///
203
+ /// // Map and append the two AssocLists
204
+ /// let newMap =
205
+ /// AssocList.disjDisjoint<Nat, Nat, Text, Text>(
206
+ /// map1,
207
+ /// map2,
208
+ /// func((v1, v2) : (?Nat, ?Text)) {
209
+ /// switch(v1, v2) {
210
+ /// case(?v1, null) {
211
+ /// debug_show(v1) // convert values from map1 to Text
212
+ /// };
213
+ /// case(null, ?v2) {
214
+ /// v2 // keep values from map2 as Text
215
+ /// };
216
+ /// case _ {
217
+ /// trap "These cases will never happen in mapAppend"
218
+ /// }
219
+ /// }
220
+ /// }
221
+ /// );
222
+ ///
223
+ /// List.toArray(newMap)
224
+ /// ```
225
+ /// Runtime: O(size1 + size2)
226
+ ///
227
+ /// Space: O(1)
228
+ ///
229
+ /// *Runtime and space assumes that `f` runs in O(1) time and space.
230
+ public func disjDisjoint<K, V, W, X>(
231
+ map1 : AssocList<K, V>,
232
+ map2 : AssocList<K, W>,
233
+ f : (?V, ?W) -> X
234
+ ) : AssocList<K, X> = label profile_assocList_disjDisjoint : AssocList<K, X> {
235
+ mapAppend<K, V, W, X>(map1, map2, f)
236
+ };
237
+
238
+ /// Creates a new map by merging entries from `map1` and `map2`, and mapping
239
+ /// them using `combine`. `combine` is also used to combine the values of colliding keys.
240
+ /// Keys are compared using the given `equal` function.
241
+ ///
242
+ /// NOTE: `combine` will never be applied to `(null, null)`.
243
+ ///
244
+ /// Example:
245
+ /// ```motoko include=import,initialize
246
+ /// import { trap } "mo:base/Debug";
247
+ ///
248
+ /// // Create map1 = [(0, 10), (1, 11), (2, 12)]
249
+ /// var map1 : AssocList<Nat, Nat> = null;
250
+ /// map1 := AssocList.replace(map1, 0, Nat.equal, ?10).0;
251
+ /// map1 := AssocList.replace(map1, 1, Nat.equal, ?11).0;
252
+ /// map1 := AssocList.replace(map1, 2, Nat.equal, ?12).0;
253
+ ///
254
+ /// // Create map2 = [(2, 12), (3, 13)]
255
+ /// var map2 : AssocList<Nat, Nat> = null;
256
+ /// map2 := AssocList.replace(map2, 2, Nat.equal, ?12).0;
257
+ /// map2 := AssocList.replace(map2, 3, Nat.equal, ?13).0;
258
+ ///
259
+ /// // Merge the two maps using `combine`
260
+ /// let newMap =
261
+ /// AssocList.disj<Nat, Nat, Nat, Nat>(
262
+ /// map1,
263
+ /// map2,
264
+ /// Nat.equal,
265
+ /// func((v1, v2) : (?Nat, ?Nat)) : Nat {
266
+ /// switch(v1, v2) {
267
+ /// case(?v1, ?v2) {
268
+ /// v1 + v2 // combine values of colliding keys by adding them
269
+ /// };
270
+ /// case(?v1, null) {
271
+ /// v1 // when a key doesn't collide, keep the original value
272
+ /// };
273
+ /// case(null, ?v2) {
274
+ /// v2
275
+ /// };
276
+ /// case _ {
277
+ /// trap "This case will never happen in disj"
278
+ /// }
279
+ /// }
280
+ /// }
281
+ /// );
282
+ ///
283
+ /// List.toArray(newMap)
284
+ /// ```
285
+ /// Runtime: O(size1 * size2)
286
+ ///
287
+ /// Space: O(size1 + size2)
288
+ ///
289
+ /// *Runtime and space assumes that `equal` and `combine` runs in O(1) time and space.
290
+ public func disj<K, V, W, X>(
291
+ map1 : AssocList<K, V>,
292
+ map2 : AssocList<K, W>,
293
+ equal : (K, K) -> Bool,
294
+ combine : (?V, ?W) -> X
295
+ ) : AssocList<K, X> {
296
+ func rec1(al1Rec : AssocList<K, V>) : AssocList<K, X> {
297
+ switch al1Rec {
298
+ case (null) {
299
+ func rec2(al2 : AssocList<K, W>) : AssocList<K, X> {
300
+ switch al2 {
301
+ case (null) { null };
302
+ case (?((k, v2), tl)) {
303
+ switch (find<K, V>(map1, k, equal)) {
304
+ case (null) { ?((k, combine(null, ?v2)), rec2(tl)) };
305
+ case (?v1) { ?((k, combine(?v1, ?v2)), rec2(tl)) }
306
+ }
307
+ }
308
+ }
309
+ };
310
+ rec2(map2)
311
+ };
312
+ case (?((k, v1), tl)) {
313
+ switch (find<K, W>(map2, k, equal)) {
314
+ case (null) { ?((k, combine(?v1, null)), rec1(tl)) };
315
+ case (?v2) { /* handled above */ rec1(tl) }
316
+ }
317
+ }
318
+ }
319
+ };
320
+ rec1(map1)
321
+ };
322
+
323
+ /// Takes the intersection of `map1` and `map2`, only keeping colliding keys
324
+ /// and combining values using the `combine` function. Keys are compared using
325
+ /// the `equal` function.
326
+ ///
327
+ /// Example:
328
+ /// ```motoko include=import,initialize
329
+ /// // Create map1 = [(0, 10), (1, 11), (2, 12)]
330
+ /// var map1 : AssocList<Nat, Nat> = null;
331
+ /// map1 := AssocList.replace(map1, 0, Nat.equal, ?10).0;
332
+ /// map1 := AssocList.replace(map1, 1, Nat.equal, ?11).0;
333
+ /// map1 := AssocList.replace(map1, 2, Nat.equal, ?12).0;
334
+ ///
335
+ /// // Create map2 = [(2, 12), (3, 13)]
336
+ /// var map2 : AssocList<Nat, Nat> = null;
337
+ /// map2 := AssocList.replace(map2, 2, Nat.equal, ?12).0;
338
+ /// map2 := AssocList.replace(map2, 3, Nat.equal, ?13).0;
339
+ ///
340
+ /// // Take the intersection of the two maps, combining values by adding them
341
+ /// let newMap = AssocList.join<Nat, Nat, Nat, Nat>(map1, map2, Nat.equal, Nat.add);
342
+ ///
343
+ /// List.toArray(newMap)
344
+ /// ```
345
+ /// Runtime: O(size1 * size2)
346
+ ///
347
+ /// Space: O(size1 + size2)
348
+ ///
349
+ /// *Runtime and space assumes that `equal` and `combine` runs in O(1) time and space.
350
+ public func join<K, V, W, X>(
351
+ map1 : AssocList<K, V>,
352
+ map2 : AssocList<K, W>,
353
+ equal : (K, K) -> Bool,
354
+ combine : (V, W) -> X
355
+ ) : AssocList<K, X> {
356
+ func rec(al1 : AssocList<K, V>) : AssocList<K, X> {
357
+ switch al1 {
358
+ case (null) { null };
359
+ case (?((k, v1), tl)) {
360
+ switch (find<K, W>(map2, k, equal)) {
361
+ case (null) { rec(tl) };
362
+ case (?v2) { ?((k, combine(v1, v2)), rec(tl)) }
363
+ }
364
+ }
365
+ }
366
+ };
367
+ rec(map1)
368
+ };
369
+
370
+ /// Collapses the elements in `map` into a single value by starting with `base`
371
+ /// and progessively combining elements into `base` with `combine`. Iteration runs
372
+ /// left to right.
373
+ ///
374
+ /// Example:
375
+ /// ```motoko include=import,initialize
376
+ /// // Create map = [(0, 10), (1, 11), (2, 12)]
377
+ /// var map : AssocList<Nat, Nat> = null;
378
+ /// map := AssocList.replace(map, 0, Nat.equal, ?10).0;
379
+ /// map := AssocList.replace(map, 1, Nat.equal, ?11).0;
380
+ /// map := AssocList.replace(map, 2, Nat.equal, ?12).0;
381
+ ///
382
+ /// // (0 * 10) + (1 * 11) + (2 * 12)
383
+ /// AssocList.fold<Nat, Nat, Nat>(map, 0, func(k, v, sumSoFar) = (k * v) + sumSoFar)
384
+ /// ```
385
+ ///
386
+ /// Runtime: O(size)
387
+ ///
388
+ /// Space: O(size)
389
+ ///
390
+ /// *Runtime and space assumes that `combine` runs in O(1) time and space.
391
+ public func fold<K, V, X>(
392
+ map : AssocList<K, V>,
393
+ base : X,
394
+ combine : (K, V, X) -> X
395
+ ) : X {
396
+ func rec(al : AssocList<K, V>) : X {
397
+ switch al {
398
+ case null { base };
399
+ case (?((k, v), t)) { combine(k, v, rec(t)) }
400
+ }
401
+ };
402
+ rec(map)
403
+ }
404
+ }
@@ -0,0 +1,212 @@
1
+ /// Module for working with Blobs: immutable sequence of bytes.
2
+ ///
3
+ /// Blobs represent sequences of bytes. They are immutable, iterable, but not indexable and can be empty.
4
+ ///
5
+ /// Byte sequences are also often represented as `[Nat8]`, i.e. an array of bytes, but this representation is currently much less compact than `Blob`, taking 4 physical bytes to represent each logical byte in the sequence.
6
+ /// If you would like to manipulate Blobs, it is recommended that you convert
7
+ /// Blobs to `[var Nat8]` or `Buffer<Nat8>`, do the manipulation, then convert back.
8
+ ///
9
+ /// Import from the base library to use this module.
10
+ /// ```motoko name=import
11
+ /// import Blob "mo:base/Blob";
12
+ /// ```
13
+ ///
14
+ /// Some built in features not listed in this module:
15
+ ///
16
+ /// * You can create a `Blob` literal from a `Text` literal, provided the context expects an expression of type `Blob`.
17
+ /// * `b.size() : Nat` returns the number of bytes in the blob `b`;
18
+ /// * `b.vals() : Iter.Iter<Nat8>` returns an iterator to enumerate the bytes of the blob `b`.
19
+ ///
20
+ /// For example:
21
+ /// ```motoko include=import
22
+ /// import Debug "mo:base/Debug";
23
+ /// import Nat8 "mo:base/Nat8";
24
+ ///
25
+ /// let blob = "\00\00\00\ff" : Blob; // blob literals, where each byte is delimited by a back-slash and represented in hex
26
+ /// let blob2 = "charsもあり" : Blob; // you can also use characters in the literals
27
+ /// let numBytes = blob.size(); // => 4 (returns the number of bytes in the Blob)
28
+ /// for (byte : Nat8 in blob.vals()) { // iterator over the Blob
29
+ /// Debug.print(Nat8.toText(byte))
30
+ /// }
31
+ /// ```
32
+ import Prim "mo:⛔";
33
+ module {
34
+ public type Blob = Prim.Types.Blob;
35
+ /// Creates a `Blob` from an array of bytes (`[Nat8]`), by copying each element.
36
+ ///
37
+ /// Example:
38
+ /// ```motoko include=import
39
+ /// let bytes : [Nat8] = [0, 255, 0];
40
+ /// let blob = Blob.fromArray(bytes); // => "\00\FF\00"
41
+ /// ```
42
+ public func fromArray(bytes : [Nat8]) : Blob = Prim.arrayToBlob bytes;
43
+
44
+ /// Creates a `Blob` from a mutable array of bytes (`[var Nat8]`), by copying each element.
45
+ ///
46
+ /// Example:
47
+ /// ```motoko include=import
48
+ /// let bytes : [var Nat8] = [var 0, 255, 0];
49
+ /// let blob = Blob.fromArrayMut(bytes); // => "\00\FF\00"
50
+ /// ```
51
+ public func fromArrayMut(bytes : [var Nat8]) : Blob = Prim.arrayMutToBlob bytes;
52
+
53
+ /// Converts a `Blob` to an array of bytes (`[Nat8]`), by copying each element.
54
+ ///
55
+ /// Example:
56
+ /// ```motoko include=import
57
+ /// let blob = "\00\FF\00" : Blob;
58
+ /// let bytes = Blob.toArray(blob); // => [0, 255, 0]
59
+ /// ```
60
+ public func toArray(blob : Blob) : [Nat8] = Prim.blobToArray blob;
61
+
62
+ /// Converts a `Blob` to a mutable array of bytes (`[var Nat8]`), by copying each element.
63
+ ///
64
+ /// Example:
65
+ /// ```motoko include=import
66
+ /// let blob = "\00\FF\00" : Blob;
67
+ /// let bytes = Blob.toArrayMut(blob); // => [var 0, 255, 0]
68
+ /// ```
69
+ public func toArrayMut(blob : Blob) : [var Nat8] = Prim.blobToArrayMut blob;
70
+
71
+ /// Returns the (non-cryptographic) hash of `blob`.
72
+ ///
73
+ /// Example:
74
+ /// ```motoko include=import
75
+ /// let blob = "\00\FF\00" : Blob;
76
+ /// Blob.hash(blob) // => 1_818_567_776
77
+ /// ```
78
+ public func hash(blob : Blob) : Nat32 = Prim.hashBlob blob;
79
+
80
+ /// General purpose comparison function for `Blob` by comparing the value of
81
+ /// the bytes. Returns the `Order` (either `#less`, `#equal`, or `#greater`)
82
+ /// by comparing `blob1` with `blob2`.
83
+ ///
84
+ /// Example:
85
+ /// ```motoko include=import
86
+ /// let blob1 = "\00\00\00" : Blob;
87
+ /// let blob2 = "\00\FF\00" : Blob;
88
+ /// Blob.compare(blob1, blob2) // => #less
89
+ /// ```
90
+ public func compare(blob1 : Blob, blob2 : Blob) : { #less; #equal; #greater } {
91
+ if (blob1 < blob2) {
92
+ #less
93
+ } else if (blob1 == blob2) {
94
+ #equal
95
+ } else {
96
+ #greater
97
+ }
98
+ };
99
+
100
+ /// Equality function for `Blob` types.
101
+ /// This is equivalent to `blob1 == blob2`.
102
+ ///
103
+ /// Example:
104
+ /// ```motoko include=import
105
+ /// let blob1 = "\00\FF\00" : Blob;
106
+ /// let blob2 = "\00\FF\00" : Blob;
107
+ /// ignore Blob.equal(blob1, blob2);
108
+ /// blob1 == blob2 // => true
109
+ /// ```
110
+ ///
111
+ /// Note: The reason why this function is defined in this library (in addition
112
+ /// to the existing `==` operator) is so that you can use it as a function value
113
+ /// to pass to a higher order function. It is not possible to use `==` as a
114
+ /// function value at the moment.
115
+ ///
116
+ /// Example:
117
+ /// ```motoko include=import
118
+ /// import Buffer "mo:base/Buffer";
119
+ ///
120
+ /// let buffer1 = Buffer.Buffer<Blob>(3);
121
+ /// let buffer2 = Buffer.Buffer<Blob>(3);
122
+ /// Buffer.equal(buffer1, buffer2, Blob.equal) // => true
123
+ /// ```
124
+ public func equal(blob1 : Blob, blob2 : Blob) : Bool { blob1 == blob2 };
125
+
126
+ /// Inequality function for `Blob` types.
127
+ /// This is equivalent to `blob1 != blob2`.
128
+ ///
129
+ /// Example:
130
+ /// ```motoko include=import
131
+ /// let blob1 = "\00\AA\AA" : Blob;
132
+ /// let blob2 = "\00\FF\00" : Blob;
133
+ /// ignore Blob.notEqual(blob1, blob2);
134
+ /// blob1 != blob2 // => true
135
+ /// ```
136
+ ///
137
+ /// Note: The reason why this function is defined in this library (in addition
138
+ /// to the existing `!=` operator) is so that you can use it as a function value
139
+ /// to pass to a higher order function. It is not possible to use `!=` as a
140
+ /// function value at the moment.
141
+ public func notEqual(blob1 : Blob, blob2 : Blob) : Bool { blob1 != blob2 };
142
+
143
+ /// "Less than" function for `Blob` types.
144
+ /// This is equivalent to `blob1 < blob2`.
145
+ ///
146
+ /// Example:
147
+ /// ```motoko include=import
148
+ /// let blob1 = "\00\AA\AA" : Blob;
149
+ /// let blob2 = "\00\FF\00" : Blob;
150
+ /// ignore Blob.less(blob1, blob2);
151
+ /// blob1 < blob2 // => true
152
+ /// ```
153
+ ///
154
+ /// Note: The reason why this function is defined in this library (in addition
155
+ /// to the existing `<` operator) is so that you can use it as a function value
156
+ /// to pass to a higher order function. It is not possible to use `<` as a
157
+ /// function value at the moment.
158
+ public func less(blob1 : Blob, blob2 : Blob) : Bool { blob1 < blob2 };
159
+
160
+ /// "Less than or equal to" function for `Blob` types.
161
+ /// This is equivalent to `blob1 <= blob2`.
162
+ ///
163
+ /// Example:
164
+ /// ```motoko include=import
165
+ /// let blob1 = "\00\AA\AA" : Blob;
166
+ /// let blob2 = "\00\FF\00" : Blob;
167
+ /// ignore Blob.lessOrEqual(blob1, blob2);
168
+ /// blob1 <= blob2 // => true
169
+ /// ```
170
+ ///
171
+ /// Note: The reason why this function is defined in this library (in addition
172
+ /// to the existing `<=` operator) is so that you can use it as a function value
173
+ /// to pass to a higher order function. It is not possible to use `<=` as a
174
+ /// function value at the moment.
175
+ public func lessOrEqual(blob1 : Blob, blob2 : Blob) : Bool { blob1 <= blob2 };
176
+
177
+ /// "Greater than" function for `Blob` types.
178
+ /// This is equivalent to `blob1 > blob2`.
179
+ ///
180
+ /// Example:
181
+ /// ```motoko include=import
182
+ /// let blob1 = "\BB\AA\AA" : Blob;
183
+ /// let blob2 = "\00\00\00" : Blob;
184
+ /// ignore Blob.greater(blob1, blob2);
185
+ /// blob1 > blob2 // => true
186
+ /// ```
187
+ ///
188
+ /// Note: The reason why this function is defined in this library (in addition
189
+ /// to the existing `>` operator) is so that you can use it as a function value
190
+ /// to pass to a higher order function. It is not possible to use `>` as a
191
+ /// function value at the moment.
192
+ public func greater(blob1 : Blob, blob2 : Blob) : Bool { blob1 > blob2 };
193
+
194
+ /// "Greater than or equal to" function for `Blob` types.
195
+ /// This is equivalent to `blob1 >= blob2`.
196
+ ///
197
+ /// Example:
198
+ /// ```motoko include=import
199
+ /// let blob1 = "\BB\AA\AA" : Blob;
200
+ /// let blob2 = "\00\00\00" : Blob;
201
+ /// ignore Blob.greaterOrEqual(blob1, blob2);
202
+ /// blob1 >= blob2 // => true
203
+ /// ```
204
+ ///
205
+ /// Note: The reason why this function is defined in this library (in addition
206
+ /// to the existing `>=` operator) is so that you can use it as a function value
207
+ /// to pass to a higher order function. It is not possible to use `>=` as a
208
+ /// function value at the moment.
209
+ public func greaterOrEqual(blob1 : Blob, blob2 : Blob) : Bool {
210
+ blob1 >= blob2
211
+ }
212
+ }
@@ -0,0 +1,44 @@
1
+ /// Boolean type and operations.
2
+ ///
3
+ /// While boolean operators `_ and _` and `_ or _` are short-circuiting,
4
+ /// avoiding computation of the right argument when possible, the functions
5
+ /// `logand(_, _)` and `logor(_, _)` are *strict* and will always evaluate *both*
6
+ /// of their arguments.
7
+
8
+ import Prim "mo:⛔";
9
+ module {
10
+
11
+ /// Booleans with constants `true` and `false`.
12
+ public type Bool = Prim.Types.Bool;
13
+
14
+ /// Conversion.
15
+ public func toText(x : Bool) : Text {
16
+ if x { "true" } else { "false" }
17
+ };
18
+
19
+ /// Returns `x and y`.
20
+ public func logand(x : Bool, y : Bool) : Bool { x and y };
21
+
22
+ /// Returns `x or y`.
23
+ public func logor(x : Bool, y : Bool) : Bool { x or y };
24
+
25
+ /// Returns exclusive or of `x` and `y`, `x != y`.
26
+ public func logxor(x : Bool, y : Bool) : Bool {
27
+ x != y
28
+ };
29
+
30
+ /// Returns `not x`.
31
+ public func lognot(x : Bool) : Bool { not x };
32
+
33
+ /// Returns `x == y`.
34
+ public func equal(x : Bool, y : Bool) : Bool { x == y };
35
+
36
+ /// Returns `x != y`.
37
+ public func notEqual(x : Bool, y : Bool) : Bool { x != y };
38
+
39
+ /// Returns the order of `x` and `y`, where `false < true`.
40
+ public func compare(x : Bool, y : Bool) : { #less; #equal; #greater } {
41
+ if (x == y) { #equal } else if (x) { #greater } else { #less }
42
+ };
43
+
44
+ }