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.
- package/package.json +3 -1
- package/.mops/base@0.7.4/LICENSE +0 -208
- package/.mops/base@0.7.4/README.md +0 -64
- package/.mops/base@0.7.4/mops.toml +0 -5
- package/.mops/base@0.7.4/src/Array.mo +0 -686
- package/.mops/base@0.7.4/src/AssocList.mo +0 -203
- package/.mops/base@0.7.4/src/Blob.mo +0 -55
- package/.mops/base@0.7.4/src/Bool.mo +0 -44
- package/.mops/base@0.7.4/src/Buffer.mo +0 -1937
- package/.mops/base@0.7.4/src/CertifiedData.mo +0 -29
- package/.mops/base@0.7.4/src/Char.mo +0 -67
- package/.mops/base@0.7.4/src/Debug.mo +0 -15
- package/.mops/base@0.7.4/src/Deque.mo +0 -75
- package/.mops/base@0.7.4/src/Error.mo +0 -41
- package/.mops/base@0.7.4/src/ExperimentalCycles.mo +0 -51
- package/.mops/base@0.7.4/src/ExperimentalInternetComputer.mo +0 -36
- package/.mops/base@0.7.4/src/ExperimentalStableMemory.mo +0 -121
- package/.mops/base@0.7.4/src/Float.mo +0 -150
- package/.mops/base@0.7.4/src/Func.mo +0 -38
- package/.mops/base@0.7.4/src/Hash.mo +0 -83
- package/.mops/base@0.7.4/src/HashMap.mo +0 -229
- package/.mops/base@0.7.4/src/Heap.mo +0 -113
- package/.mops/base@0.7.4/src/Int.mo +0 -150
- package/.mops/base@0.7.4/src/Int16.mo +0 -159
- package/.mops/base@0.7.4/src/Int32.mo +0 -160
- package/.mops/base@0.7.4/src/Int64.mo +0 -161
- package/.mops/base@0.7.4/src/Int8.mo +0 -160
- package/.mops/base@0.7.4/src/Iter.mo +0 -220
- package/.mops/base@0.7.4/src/IterType.mo +0 -7
- package/.mops/base@0.7.4/src/List.mo +0 -433
- package/.mops/base@0.7.4/src/Nat.mo +0 -75
- package/.mops/base@0.7.4/src/Nat16.mo +0 -146
- package/.mops/base@0.7.4/src/Nat32.mo +0 -146
- package/.mops/base@0.7.4/src/Nat64.mo +0 -146
- package/.mops/base@0.7.4/src/Nat8.mo +0 -146
- package/.mops/base@0.7.4/src/None.mo +0 -19
- package/.mops/base@0.7.4/src/Option.mo +0 -160
- package/.mops/base@0.7.4/src/Order.mo +0 -46
- package/.mops/base@0.7.4/src/Prelude.mo +0 -33
- package/.mops/base@0.7.4/src/Principal.mo +0 -58
- package/.mops/base@0.7.4/src/RBTree.mo +0 -218
- package/.mops/base@0.7.4/src/Random.mo +0 -188
- package/.mops/base@0.7.4/src/Result.mo +0 -210
- package/.mops/base@0.7.4/src/Stack.mo +0 -40
- package/.mops/base@0.7.4/src/Text.mo +0 -615
- package/.mops/base@0.7.4/src/Time.mo +0 -37
- package/.mops/base@0.7.4/src/Trie.mo +0 -1200
- package/.mops/base@0.7.4/src/TrieMap.mo +0 -180
- package/.mops/base@0.7.4/src/TrieSet.mo +0 -97
- package/.mops/base@0.8.3/LICENSE +0 -208
- package/.mops/base@0.8.3/README.md +0 -64
- package/.mops/base@0.8.3/mops.toml +0 -6
- package/.mops/base@0.8.3/src/Array.mo +0 -717
- package/.mops/base@0.8.3/src/AssocList.mo +0 -404
- package/.mops/base@0.8.3/src/Blob.mo +0 -212
- package/.mops/base@0.8.3/src/Bool.mo +0 -44
- package/.mops/base@0.8.3/src/Buffer.mo +0 -2660
- package/.mops/base@0.8.3/src/CertifiedData.mo +0 -53
- package/.mops/base@0.8.3/src/Char.mo +0 -65
- package/.mops/base@0.8.3/src/Debug.mo +0 -56
- package/.mops/base@0.8.3/src/Deque.mo +0 -243
- package/.mops/base@0.8.3/src/Error.mo +0 -68
- package/.mops/base@0.8.3/src/ExperimentalCycles.mo +0 -151
- package/.mops/base@0.8.3/src/ExperimentalInternetComputer.mo +0 -60
- package/.mops/base@0.8.3/src/ExperimentalStableMemory.mo +0 -348
- package/.mops/base@0.8.3/src/Float.mo +0 -843
- package/.mops/base@0.8.3/src/Func.mo +0 -46
- package/.mops/base@0.8.3/src/Hash.mo +0 -82
- package/.mops/base@0.8.3/src/HashMap.mo +0 -457
- package/.mops/base@0.8.3/src/Heap.mo +0 -233
- package/.mops/base@0.8.3/src/Int.mo +0 -365
- package/.mops/base@0.8.3/src/Int16.mo +0 -521
- package/.mops/base@0.8.3/src/Int32.mo +0 -522
- package/.mops/base@0.8.3/src/Int64.mo +0 -522
- package/.mops/base@0.8.3/src/Int8.mo +0 -522
- package/.mops/base@0.8.3/src/Iter.mo +0 -227
- package/.mops/base@0.8.3/src/IterType.mo +0 -7
- package/.mops/base@0.8.3/src/List.mo +0 -930
- package/.mops/base@0.8.3/src/Nat.mo +0 -305
- package/.mops/base@0.8.3/src/Nat16.mo +0 -144
- package/.mops/base@0.8.3/src/Nat32.mo +0 -144
- package/.mops/base@0.8.3/src/Nat64.mo +0 -144
- package/.mops/base@0.8.3/src/Nat8.mo +0 -144
- package/.mops/base@0.8.3/src/None.mo +0 -19
- package/.mops/base@0.8.3/src/Option.mo +0 -154
- package/.mops/base@0.8.3/src/Order.mo +0 -46
- package/.mops/base@0.8.3/src/Prelude.mo +0 -33
- package/.mops/base@0.8.3/src/Principal.mo +0 -249
- package/.mops/base@0.8.3/src/RBTree.mo +0 -681
- package/.mops/base@0.8.3/src/Random.mo +0 -270
- package/.mops/base@0.8.3/src/Result.mo +0 -209
- package/.mops/base@0.8.3/src/Stack.mo +0 -93
- package/.mops/base@0.8.3/src/Text.mo +0 -761
- package/.mops/base@0.8.3/src/Time.mo +0 -36
- package/.mops/base@0.8.3/src/Timer.mo +0 -62
- package/.mops/base@0.8.3/src/Trie.mo +0 -1603
- package/.mops/base@0.8.3/src/TrieMap.mo +0 -392
- package/.mops/base@0.8.3/src/TrieSet.mo +0 -148
- package/network.txt +0 -1
|
@@ -1,930 +0,0 @@
|
|
|
1
|
-
/// Purely-functional, singly-linked lists.
|
|
2
|
-
|
|
3
|
-
/// A list of type `List<T>` is either `null` or an optional pair of a value of type `T` and a tail, itself of type `List<T>`.
|
|
4
|
-
///
|
|
5
|
-
/// To use this library, import it using:
|
|
6
|
-
///
|
|
7
|
-
/// ```motoko name=initialize
|
|
8
|
-
/// import List "mo:base/List";
|
|
9
|
-
/// ```
|
|
10
|
-
|
|
11
|
-
import Array "Array";
|
|
12
|
-
import Iter "IterType";
|
|
13
|
-
import Option "Option";
|
|
14
|
-
import Order "Order";
|
|
15
|
-
import Result "Result";
|
|
16
|
-
|
|
17
|
-
module {
|
|
18
|
-
|
|
19
|
-
// A singly-linked list consists of zero or more _cons cells_, wherein
|
|
20
|
-
// each cell contains a single list element (the cell's _head_), and a pointer to the
|
|
21
|
-
// remainder of the list (the cell's _tail_).
|
|
22
|
-
public type List<T> = ?(T, List<T>);
|
|
23
|
-
|
|
24
|
-
/// Create an empty list.
|
|
25
|
-
///
|
|
26
|
-
/// Example:
|
|
27
|
-
/// ```motoko include=initialize
|
|
28
|
-
/// List.nil<Nat>() // => null
|
|
29
|
-
/// ```
|
|
30
|
-
///
|
|
31
|
-
/// Runtime: O(1)
|
|
32
|
-
///
|
|
33
|
-
/// Space: O(1)
|
|
34
|
-
public func nil<T>() : List<T> = null;
|
|
35
|
-
|
|
36
|
-
/// Check whether a list is empty and return true if the list is empty.
|
|
37
|
-
///
|
|
38
|
-
/// Example:
|
|
39
|
-
/// ```motoko include=initialize
|
|
40
|
-
/// List.isNil<Nat>(null) // => true
|
|
41
|
-
/// ```
|
|
42
|
-
///
|
|
43
|
-
/// Runtime: O(1)
|
|
44
|
-
///
|
|
45
|
-
/// Space: O(1)
|
|
46
|
-
public func isNil<T>(l : List<T>) : Bool {
|
|
47
|
-
switch l {
|
|
48
|
-
case null { true };
|
|
49
|
-
case _ { false }
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
/// Add `x` to the head of `list`, and return the new list.
|
|
54
|
-
///
|
|
55
|
-
/// Example:
|
|
56
|
-
/// ```motoko include=initialize
|
|
57
|
-
/// List.push<Nat>(0, null) // => ?(0, null);
|
|
58
|
-
/// ```
|
|
59
|
-
///
|
|
60
|
-
/// Runtime: O(1)
|
|
61
|
-
///
|
|
62
|
-
/// Space: O(1)
|
|
63
|
-
public func push<T>(x : T, l : List<T>) : List<T> = ?(x, l);
|
|
64
|
-
|
|
65
|
-
/// Return the last element of the list, if present.
|
|
66
|
-
/// Example:
|
|
67
|
-
/// ```motoko include=initialize
|
|
68
|
-
/// List.last<Nat>(?(0, ?(1, null))) // => ?1
|
|
69
|
-
/// ```
|
|
70
|
-
///
|
|
71
|
-
/// Runtime: O(size)
|
|
72
|
-
///
|
|
73
|
-
/// Space: O(1)
|
|
74
|
-
public func last<T>(l : List<T>) : ?T {
|
|
75
|
-
switch l {
|
|
76
|
-
case null { null };
|
|
77
|
-
case (?(x, null)) { ?x };
|
|
78
|
-
case (?(_, t)) { last<T>(t) }
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
/// Remove the head of the list, returning the optioned head and the tail of the list in a pair.
|
|
83
|
-
/// Returns `(null, null)` if the list is empty.
|
|
84
|
-
///
|
|
85
|
-
/// Example:
|
|
86
|
-
/// ```motoko include=initialize
|
|
87
|
-
/// List.pop<Nat>(?(0, ?(1, null))) // => (?0, ?(1, null))
|
|
88
|
-
/// ```
|
|
89
|
-
///
|
|
90
|
-
/// Runtime: O(1)
|
|
91
|
-
///
|
|
92
|
-
/// Space: O(1)
|
|
93
|
-
public func pop<T>(l : List<T>) : (?T, List<T>) {
|
|
94
|
-
switch l {
|
|
95
|
-
case null { (null, null) };
|
|
96
|
-
case (?(h, t)) { (?h, t) }
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
/// Return the length of the list.
|
|
101
|
-
///
|
|
102
|
-
/// Example:
|
|
103
|
-
/// ```motoko include=initialize
|
|
104
|
-
/// List.size<Nat>(?(0, ?(1, null))) // => 2
|
|
105
|
-
/// ```
|
|
106
|
-
///
|
|
107
|
-
/// Runtime: O(size)
|
|
108
|
-
///
|
|
109
|
-
/// Space: O(1)
|
|
110
|
-
public func size<T>(l : List<T>) : Nat {
|
|
111
|
-
func rec(l : List<T>, n : Nat) : Nat {
|
|
112
|
-
switch l {
|
|
113
|
-
case null { n };
|
|
114
|
-
case (?(_, t)) { rec(t, n + 1) }
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
rec(l, 0)
|
|
118
|
-
};
|
|
119
|
-
/// Access any item in a list, zero-based.
|
|
120
|
-
///
|
|
121
|
-
/// NOTE: Indexing into a list is a linear operation, and usually an
|
|
122
|
-
/// indication that a list might not be the best data structure
|
|
123
|
-
/// to use.
|
|
124
|
-
///
|
|
125
|
-
/// Example:
|
|
126
|
-
/// ```motoko include=initialize
|
|
127
|
-
/// List.get<Nat>(?(0, ?(1, null)), 1) // => ?1
|
|
128
|
-
/// ```
|
|
129
|
-
///
|
|
130
|
-
/// Runtime: O(size)
|
|
131
|
-
///
|
|
132
|
-
/// Space: O(1)
|
|
133
|
-
public func get<T>(l : List<T>, n : Nat) : ?T {
|
|
134
|
-
switch (n, l) {
|
|
135
|
-
case (_, null) { null };
|
|
136
|
-
case (0, (?(h, t))) { ?h };
|
|
137
|
-
case (_, (?(_, t))) { get<T>(t, n - 1) }
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
/// Reverses the list.
|
|
142
|
-
///
|
|
143
|
-
/// Example:
|
|
144
|
-
/// ```motoko include=initialize
|
|
145
|
-
/// List.reverse<Nat>(?(0, ?(1, ?(2, null)))) // => ?(2, ?(1, ?(0, null)))
|
|
146
|
-
/// ```
|
|
147
|
-
///
|
|
148
|
-
/// Runtime: O(size)
|
|
149
|
-
///
|
|
150
|
-
/// Space: O(size)
|
|
151
|
-
public func reverse<T>(l : List<T>) : List<T> {
|
|
152
|
-
func rec(l : List<T>, r : List<T>) : List<T> {
|
|
153
|
-
switch l {
|
|
154
|
-
case null { r };
|
|
155
|
-
case (?(h, t)) { rec(t, ?(h, r)) }
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
rec(l, null)
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
/// Call the given function for its side effect, with each list element in turn.
|
|
162
|
-
///
|
|
163
|
-
/// Example:
|
|
164
|
-
/// ```motoko include=initialize
|
|
165
|
-
/// var sum = 0;
|
|
166
|
-
/// List.iterate<Nat>(?(0, ?(1, ?(2, null))), func n { sum += n });
|
|
167
|
-
/// sum // => 3
|
|
168
|
-
/// ```
|
|
169
|
-
///
|
|
170
|
-
/// Runtime: O(size)
|
|
171
|
-
///
|
|
172
|
-
/// Space: O(1)
|
|
173
|
-
public func iterate<T>(l : List<T>, f : T -> ()) {
|
|
174
|
-
switch l {
|
|
175
|
-
case null { () };
|
|
176
|
-
case (?(h, t)) { f(h); iterate<T>(t, f) }
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
/// Call the given function `f` on each list element and collect the results
|
|
181
|
-
/// in a new list.
|
|
182
|
-
///
|
|
183
|
-
/// Example:
|
|
184
|
-
/// ```motoko include=initialize
|
|
185
|
-
/// import Nat = "mo:base/Nat"
|
|
186
|
-
/// List.map<Nat, Text>(?(0, ?(1, ?(2, null))), Nat.toText) // => ?("0", ?("1", ?("2", null))
|
|
187
|
-
/// ```
|
|
188
|
-
///
|
|
189
|
-
/// Runtime: O(size)
|
|
190
|
-
///
|
|
191
|
-
/// Space: O(size)
|
|
192
|
-
/// *Runtime and space assumes that `f` runs in O(1) time and space.
|
|
193
|
-
public func map<T, U>(l : List<T>, f : T -> U) : List<U> {
|
|
194
|
-
switch l {
|
|
195
|
-
case null { null };
|
|
196
|
-
case (?(h, t)) { ?(f(h), map<T, U>(t, f)) }
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
/// Create a new list with only those elements of the original list for which
|
|
201
|
-
/// the given function (often called the _predicate_) returns true.
|
|
202
|
-
///
|
|
203
|
-
/// Example:
|
|
204
|
-
/// ```motoko include=initialize
|
|
205
|
-
/// List.filter<Nat>(?(0, ?(1, ?(2, null))), func n { n != 1 }) // => ?(0, ?(2, null))
|
|
206
|
-
/// ```
|
|
207
|
-
///
|
|
208
|
-
/// Runtime: O(size)
|
|
209
|
-
///
|
|
210
|
-
/// Space: O(size)
|
|
211
|
-
public func filter<T>(l : List<T>, f : T -> Bool) : List<T> {
|
|
212
|
-
switch l {
|
|
213
|
-
case null { null };
|
|
214
|
-
case (?(h, t)) {
|
|
215
|
-
if (f(h)) {
|
|
216
|
-
?(h, filter<T>(t, f))
|
|
217
|
-
} else {
|
|
218
|
-
filter<T>(t, f)
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
/// Create two new lists from the results of a given function (`f`).
|
|
225
|
-
/// The first list only includes the elements for which the given
|
|
226
|
-
/// function `f` returns true and the second list only includes
|
|
227
|
-
/// the elements for which the function returns false.
|
|
228
|
-
///
|
|
229
|
-
/// Example:
|
|
230
|
-
/// ```motoko include=initialize
|
|
231
|
-
/// List.partition<Nat>(?(0, ?(1, ?(2, null))), func n { n != 1 }) // => (?(0, ?(2, null)), ?(1, null))
|
|
232
|
-
/// ```
|
|
233
|
-
///
|
|
234
|
-
/// Runtime: O(size)
|
|
235
|
-
///
|
|
236
|
-
/// Space: O(size)
|
|
237
|
-
public func partition<T>(l : List<T>, f : T -> Bool) : (List<T>, List<T>) {
|
|
238
|
-
switch l {
|
|
239
|
-
case null { (null, null) };
|
|
240
|
-
case (?(h, t)) {
|
|
241
|
-
if (f(h)) {
|
|
242
|
-
// call f in-order
|
|
243
|
-
let (l, r) = partition<T>(t, f);
|
|
244
|
-
(?(h, l), r)
|
|
245
|
-
} else {
|
|
246
|
-
let (l, r) = partition<T>(t, f);
|
|
247
|
-
(l, ?(h, r))
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
/// Call the given function on each list element, and collect the non-null results
|
|
254
|
-
/// in a new list.
|
|
255
|
-
///
|
|
256
|
-
/// Example:
|
|
257
|
-
/// ```motoko include=initialize
|
|
258
|
-
/// List.mapFilter<Nat, Nat>(
|
|
259
|
-
/// ?(1, ?(2, ?(3, null))),
|
|
260
|
-
/// func n {
|
|
261
|
-
/// if (n > 1) {
|
|
262
|
-
/// ?(n * 2);
|
|
263
|
-
/// } else {
|
|
264
|
-
/// null
|
|
265
|
-
/// }
|
|
266
|
-
/// }
|
|
267
|
-
/// ) // => ?(4, ?(6, null))
|
|
268
|
-
/// ```
|
|
269
|
-
///
|
|
270
|
-
/// Runtime: O(size)
|
|
271
|
-
///
|
|
272
|
-
/// Space: O(size)
|
|
273
|
-
public func mapFilter<T, U>(l : List<T>, f : T -> ?U) : List<U> {
|
|
274
|
-
switch l {
|
|
275
|
-
case null { null };
|
|
276
|
-
case (?(h, t)) {
|
|
277
|
-
switch (f(h)) {
|
|
278
|
-
case null { mapFilter<T, U>(t, f) };
|
|
279
|
-
case (?h_) { ?(h_, mapFilter<T, U>(t, f)) }
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
/// Maps a Result-returning function `f` over a List and returns either
|
|
286
|
-
/// the first error or a list of successful values.
|
|
287
|
-
///
|
|
288
|
-
/// Example:
|
|
289
|
-
/// ```motoko include=initialize
|
|
290
|
-
/// List.mapResult<Nat, Nat, Text>(
|
|
291
|
-
/// ?(1, ?(2, ?(3, null))),
|
|
292
|
-
/// func n {
|
|
293
|
-
/// if (n > 0) {
|
|
294
|
-
/// #ok(n * 2);
|
|
295
|
-
/// } else {
|
|
296
|
-
/// #err("Some element is zero")
|
|
297
|
-
/// }
|
|
298
|
-
/// }
|
|
299
|
-
/// ); // => #ok ?(2, ?(4, ?(6, null))
|
|
300
|
-
/// ```
|
|
301
|
-
///
|
|
302
|
-
/// Runtime: O(size)
|
|
303
|
-
///
|
|
304
|
-
/// Space: O(size)
|
|
305
|
-
///
|
|
306
|
-
/// *Runtime and space assumes that `f` runs in O(1) time and space.
|
|
307
|
-
public func mapResult<T, R, E>(xs : List<T>, f : T -> Result.Result<R, E>) : Result.Result<List<R>, E> {
|
|
308
|
-
func go(xs : List<T>, acc : List<R>) : Result.Result<List<R>, E> {
|
|
309
|
-
switch xs {
|
|
310
|
-
case null { #ok(acc) };
|
|
311
|
-
case (?(head, tail)) {
|
|
312
|
-
switch (f(head)) {
|
|
313
|
-
case (#err(err)) { #err(err) };
|
|
314
|
-
case (#ok(ok)) { go(tail, ?(ok, acc)) }
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
Result.mapOk(go(xs, null), func(xs : List<R>) : List<R> = reverse(xs))
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
/// Append the elements from the reverse of one list, 'l', to another list, 'm'.
|
|
323
|
-
///
|
|
324
|
-
/// Example:
|
|
325
|
-
/// ```motoko include=initialize
|
|
326
|
-
/// List.revAppend<Nat>(
|
|
327
|
-
/// ?(2, ?(1, ?(0, null))),
|
|
328
|
-
/// ?(3, ?(4, ?(5, null)))
|
|
329
|
-
/// ); // => ?(0, ?(1, ?(2, ?(3, ?(4, ?(5, null))))))
|
|
330
|
-
/// ```
|
|
331
|
-
///
|
|
332
|
-
/// Runtime: O(size(l))
|
|
333
|
-
///
|
|
334
|
-
/// Space: O(size(l))
|
|
335
|
-
func revAppend<T>(l : List<T>, m : List<T>) : List<T> {
|
|
336
|
-
switch l {
|
|
337
|
-
case null { m };
|
|
338
|
-
case (?(h, t)) { revAppend(t, ?(h, m)) }
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
/// Append the elements from one list to another list.
|
|
343
|
-
///
|
|
344
|
-
/// Example:
|
|
345
|
-
/// ```motoko include=initialize
|
|
346
|
-
/// List.append<Nat>(
|
|
347
|
-
/// ?(0, ?(1, ?(2, null))),
|
|
348
|
-
/// ?(3, ?(4, ?(5, null)))
|
|
349
|
-
/// ) // => ?(0, ?(1, ?(2, ?(3, ?(4, ?(5, null))))))
|
|
350
|
-
/// ```
|
|
351
|
-
///
|
|
352
|
-
/// Runtime: O(size(l))
|
|
353
|
-
///
|
|
354
|
-
/// Space: O(size(l))
|
|
355
|
-
public func append<T>(l : List<T>, m : List<T>) : List<T> {
|
|
356
|
-
revAppend(reverse(l), m)
|
|
357
|
-
};
|
|
358
|
-
|
|
359
|
-
/// Flatten, or concatenate, a list of lists as a list.
|
|
360
|
-
///
|
|
361
|
-
/// Example:
|
|
362
|
-
/// ```motoko include=initialize
|
|
363
|
-
/// List.flatten<Nat>(
|
|
364
|
-
/// ?(?(0, ?(1, ?(2, null))),
|
|
365
|
-
/// ?(?(3, ?(4, ?(5, null))),
|
|
366
|
-
/// null))
|
|
367
|
-
/// ); // => ?(0, ?(1, ?(2, ?(3, ?(4, ?(5, null))))))
|
|
368
|
-
/// ```
|
|
369
|
-
///
|
|
370
|
-
/// Runtime: O(size*size)
|
|
371
|
-
///
|
|
372
|
-
/// Space: O(size*size)
|
|
373
|
-
public func flatten<T>(l : List<List<T>>) : List<T> {
|
|
374
|
-
//FIXME: this is quadratic, not linear https://github.com/dfinity/motoko-base/issues/459
|
|
375
|
-
foldLeft<List<T>, List<T>>(l, null, func(a, b) { append<T>(a, b) })
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
/// Returns the first `n` elements of the given list.
|
|
379
|
-
/// If the given list has fewer than `n` elements, this function returns
|
|
380
|
-
/// a copy of the full input list.
|
|
381
|
-
///
|
|
382
|
-
/// Example:
|
|
383
|
-
/// ```motoko include=initialize
|
|
384
|
-
/// List.take<Nat>(
|
|
385
|
-
/// ?(0, ?(1, ?(2, null))),
|
|
386
|
-
/// 2
|
|
387
|
-
/// ); // => ?(0, ?(1, null))
|
|
388
|
-
/// ```
|
|
389
|
-
///
|
|
390
|
-
/// Runtime: O(n)
|
|
391
|
-
///
|
|
392
|
-
/// Space: O(n)
|
|
393
|
-
public func take<T>(l : List<T>, n : Nat) : List<T> {
|
|
394
|
-
switch (l, n) {
|
|
395
|
-
case (_, 0) { null };
|
|
396
|
-
case (null, _) { null };
|
|
397
|
-
case (?(h, t), m) { ?(h, take<T>(t, m - 1)) }
|
|
398
|
-
}
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
/// Drop the first `n` elements from the given list.
|
|
402
|
-
///
|
|
403
|
-
/// Example:
|
|
404
|
-
/// ```motoko include=initialize
|
|
405
|
-
/// List.drop<Nat>(
|
|
406
|
-
/// ?(0, ?(1, ?(2, null))),
|
|
407
|
-
/// 2
|
|
408
|
-
/// ); // => ?(2, null)
|
|
409
|
-
/// ```
|
|
410
|
-
///
|
|
411
|
-
/// Runtime: O(n)
|
|
412
|
-
///
|
|
413
|
-
/// Space: O(1)
|
|
414
|
-
public func drop<T>(l : List<T>, n : Nat) : List<T> {
|
|
415
|
-
switch (l, n) {
|
|
416
|
-
case (l_, 0) { l_ };
|
|
417
|
-
case (null, _) { null };
|
|
418
|
-
case ((?(h, t)), m) { drop<T>(t, m - 1) }
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
/// Collapses the elements in `list` into a single value by starting with `base`
|
|
423
|
-
/// and progessively combining elements into `base` with `combine`. Iteration runs
|
|
424
|
-
/// left to right.
|
|
425
|
-
///
|
|
426
|
-
/// Example:
|
|
427
|
-
/// ```motoko include=initialize
|
|
428
|
-
/// import Nat "mo:base/Nat";
|
|
429
|
-
///
|
|
430
|
-
/// List.foldLeft<Nat, Text>(
|
|
431
|
-
/// ?(1, ?(2, ?(3, null))),
|
|
432
|
-
/// "",
|
|
433
|
-
/// func (acc, x) { acc # Nat.toText(x)}
|
|
434
|
-
/// ) // => "123"
|
|
435
|
-
/// ```
|
|
436
|
-
///
|
|
437
|
-
/// Runtime: O(size(list))
|
|
438
|
-
///
|
|
439
|
-
/// Space: O(1) heap, O(1) stack
|
|
440
|
-
///
|
|
441
|
-
/// *Runtime and space assumes that `combine` runs in O(1) time and space.
|
|
442
|
-
public func foldLeft<T, S>(list : List<T>, base : S, combine : (S, T) -> S) : S {
|
|
443
|
-
switch list {
|
|
444
|
-
case null { base };
|
|
445
|
-
case (?(h, t)) { foldLeft(t, combine(base, h), combine) }
|
|
446
|
-
}
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
/// Collapses the elements in `buffer` into a single value by starting with `base`
|
|
450
|
-
/// and progessively combining elements into `base` with `combine`. Iteration runs
|
|
451
|
-
/// right to left.
|
|
452
|
-
///
|
|
453
|
-
/// Example:
|
|
454
|
-
/// ```motoko include=initialize
|
|
455
|
-
/// import Nat "mo:base/Nat";
|
|
456
|
-
///
|
|
457
|
-
/// List.foldRight<Nat, Text>(
|
|
458
|
-
/// ?(1, ?(2, ?(3, null))),
|
|
459
|
-
/// "",
|
|
460
|
-
/// func (x, acc) { Nat.toText(x) # acc}
|
|
461
|
-
/// ) // => "123"
|
|
462
|
-
/// ```
|
|
463
|
-
///
|
|
464
|
-
/// Runtime: O(size(list))
|
|
465
|
-
///
|
|
466
|
-
/// Space: O(1) heap, O(size(list)) stack
|
|
467
|
-
///
|
|
468
|
-
/// *Runtime and space assumes that `combine` runs in O(1) time and space.
|
|
469
|
-
public func foldRight<T, S>(list : List<T>, base : S, combine : (T, S) -> S) : S {
|
|
470
|
-
switch list {
|
|
471
|
-
case null { base };
|
|
472
|
-
case (?(h, t)) { combine(h, foldRight<T, S>(t, base, combine)) }
|
|
473
|
-
}
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
/// Return the first element for which the given predicate `f` is true,
|
|
477
|
-
/// if such an element exists.
|
|
478
|
-
///
|
|
479
|
-
/// Example:
|
|
480
|
-
/// ```motoko include=initialize
|
|
481
|
-
///
|
|
482
|
-
/// List.find<Nat>(
|
|
483
|
-
/// ?(1, ?(2, ?(3, null))),
|
|
484
|
-
/// func n { n > 1 }
|
|
485
|
-
/// ); // => ?2
|
|
486
|
-
/// ```
|
|
487
|
-
///
|
|
488
|
-
/// Runtime: O(size)
|
|
489
|
-
///
|
|
490
|
-
/// Space: O(1)
|
|
491
|
-
///
|
|
492
|
-
/// *Runtime and space assumes that `f` runs in O(1) time and space.
|
|
493
|
-
public func find<T>(l : List<T>, f : T -> Bool) : ?T {
|
|
494
|
-
switch l {
|
|
495
|
-
case null { null };
|
|
496
|
-
case (?(h, t)) { if (f(h)) { ?h } else { find<T>(t, f) } }
|
|
497
|
-
}
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
/// Return true if there exists a list element for which
|
|
501
|
-
/// the given predicate `f` is true.
|
|
502
|
-
///
|
|
503
|
-
/// Example:
|
|
504
|
-
/// ```motoko include=initialize
|
|
505
|
-
///
|
|
506
|
-
/// List.some<Nat>(
|
|
507
|
-
/// ?(1, ?(2, ?(3, null))),
|
|
508
|
-
/// func n { n > 1 }
|
|
509
|
-
/// ) // => true
|
|
510
|
-
/// ```
|
|
511
|
-
///
|
|
512
|
-
/// Runtime: O(size(list))
|
|
513
|
-
///
|
|
514
|
-
/// Space: O(1)
|
|
515
|
-
///
|
|
516
|
-
/// *Runtime and space assumes that `f` runs in O(1) time and space.
|
|
517
|
-
public func some<T>(l : List<T>, f : T -> Bool) : Bool {
|
|
518
|
-
switch l {
|
|
519
|
-
case null { false };
|
|
520
|
-
case (?(h, t)) { f(h) or some<T>(t, f) }
|
|
521
|
-
}
|
|
522
|
-
};
|
|
523
|
-
|
|
524
|
-
/// Return true if the given predicate `f` is true for all list
|
|
525
|
-
/// elements.
|
|
526
|
-
///
|
|
527
|
-
/// Example:
|
|
528
|
-
/// ```motoko include=initialize
|
|
529
|
-
///
|
|
530
|
-
/// List.all<Nat>(
|
|
531
|
-
/// ?(1, ?(2, ?(3, null))),
|
|
532
|
-
/// func n { n > 1 }
|
|
533
|
-
/// ); // => false
|
|
534
|
-
/// ```
|
|
535
|
-
///
|
|
536
|
-
/// Runtime: O(size)
|
|
537
|
-
///
|
|
538
|
-
/// Space: O(1)
|
|
539
|
-
///
|
|
540
|
-
/// *Runtime and space assumes that `f` runs in O(1) time and space.
|
|
541
|
-
public func all<T>(l : List<T>, f : T -> Bool) : Bool {
|
|
542
|
-
switch l {
|
|
543
|
-
case null { true };
|
|
544
|
-
case (?(h, t)) { f(h) and all<T>(t, f) }
|
|
545
|
-
}
|
|
546
|
-
};
|
|
547
|
-
|
|
548
|
-
/// Merge two ordered lists into a single ordered list.
|
|
549
|
-
/// This function requires both list to be ordered as specified
|
|
550
|
-
/// by the given relation `lessThanOrEqual`.
|
|
551
|
-
///
|
|
552
|
-
/// Example:
|
|
553
|
-
/// ```motoko include=initialize
|
|
554
|
-
///
|
|
555
|
-
/// List.merge<Nat>(
|
|
556
|
-
/// ?(1, ?(2, ?(4, null))),
|
|
557
|
-
/// ?(2, ?(4, ?(6, null))),
|
|
558
|
-
/// func (n1, n2) { n1 <= n2 }
|
|
559
|
-
/// ); // => ?(1, ?(2, ?(2, ?(4, ?(4, ?(6, null))))))),
|
|
560
|
-
/// ```
|
|
561
|
-
///
|
|
562
|
-
/// Runtime: O(size(l1) + size(l2))
|
|
563
|
-
///
|
|
564
|
-
/// Space: O(size(l1) + size(l2))
|
|
565
|
-
///
|
|
566
|
-
/// *Runtime and space assumes that `lessThanOrEqual` runs in O(1) time and space.
|
|
567
|
-
// TODO: replace by merge taking a compare : (T, T) -> Order.Order function?
|
|
568
|
-
public func merge<T>(l1 : List<T>, l2 : List<T>, lessThanOrEqual : (T, T) -> Bool) : List<T> {
|
|
569
|
-
switch (l1, l2) {
|
|
570
|
-
case (null, _) { l2 };
|
|
571
|
-
case (_, null) { l1 };
|
|
572
|
-
case (?(h1, t1), ?(h2, t2)) {
|
|
573
|
-
if (lessThanOrEqual(h1, h2)) {
|
|
574
|
-
?(h1, merge<T>(t1, l2, lessThanOrEqual))
|
|
575
|
-
} else {
|
|
576
|
-
?(h2, merge<T>(l1, t2, lessThanOrEqual))
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
};
|
|
581
|
-
|
|
582
|
-
private func compareAux<T>(l1 : List<T>, l2 : List<T>, compare : (T, T) -> Order.Order) : Order.Order {
|
|
583
|
-
switch (l1, l2) {
|
|
584
|
-
case (null, null) { #equal };
|
|
585
|
-
case (null, _) { #less };
|
|
586
|
-
case (_, null) { #greater };
|
|
587
|
-
case (?(h1, t1), ?(h2, t2)) {
|
|
588
|
-
switch (compare(h1, h2)) {
|
|
589
|
-
case (#equal) { compareAux<T>(t1, t2, compare) };
|
|
590
|
-
case other { other }
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
/// Compare two lists using lexicographic ordering specified by argument function `compare`.
|
|
597
|
-
///
|
|
598
|
-
/// Example:
|
|
599
|
-
/// ```motoko include=initialize
|
|
600
|
-
/// import Nat "mo:base/Nat";
|
|
601
|
-
///
|
|
602
|
-
/// List.compare<Nat>(
|
|
603
|
-
/// ?(1, ?(2, null)),
|
|
604
|
-
/// ?(3, ?(4, null)),
|
|
605
|
-
/// Nat.compare
|
|
606
|
-
/// ) // => #less
|
|
607
|
-
/// ```
|
|
608
|
-
///
|
|
609
|
-
/// Runtime: O(size(l1))
|
|
610
|
-
///
|
|
611
|
-
/// Space: O(1)
|
|
612
|
-
///
|
|
613
|
-
/// *Runtime and space assumes that argument `compare` runs in O(1) time and space.
|
|
614
|
-
public func compare<T>(l1 : List<T>, l2 : List<T>, compare : (T, T) -> Order.Order) : Order.Order {
|
|
615
|
-
compareAux<T>(l1, l2, compare);
|
|
616
|
-
};
|
|
617
|
-
|
|
618
|
-
private func equalAux<T>(l1 : List<T>, l2 : List<T>, equal : (T, T) -> Bool) : Bool {
|
|
619
|
-
switch (l1, l2) {
|
|
620
|
-
case (?(h1, t1), ?(h2, t2)) {
|
|
621
|
-
equal(h1, h2) and equalAux<T>(t1, t2, equal)
|
|
622
|
-
};
|
|
623
|
-
case (null, null) { true };
|
|
624
|
-
case _ { false };
|
|
625
|
-
}
|
|
626
|
-
};
|
|
627
|
-
/// Compare two lists for equality using the argument function `equal` to determine equality of their elements.
|
|
628
|
-
///
|
|
629
|
-
/// Example:
|
|
630
|
-
/// ```motoko include=initialize
|
|
631
|
-
/// import Nat "mo:base/Nat";
|
|
632
|
-
///
|
|
633
|
-
/// List.equal<Nat>(
|
|
634
|
-
/// ?(1, ?(2, null)),
|
|
635
|
-
/// ?(3, ?(4, null)),
|
|
636
|
-
/// Nat.equal
|
|
637
|
-
/// ); // => false
|
|
638
|
-
/// ```
|
|
639
|
-
///
|
|
640
|
-
/// Runtime: O(size(l1))
|
|
641
|
-
///
|
|
642
|
-
/// Space: O(1)
|
|
643
|
-
///
|
|
644
|
-
/// *Runtime and space assumes that argument `equal` runs in O(1) time and space.
|
|
645
|
-
public func equal<T>(l1 : List<T>, l2 : List<T>, equal : (T, T) -> Bool) : Bool {
|
|
646
|
-
equalAux<T>(l1, l2, equal);
|
|
647
|
-
};
|
|
648
|
-
|
|
649
|
-
/// Generate a list based on a length and a function that maps from
|
|
650
|
-
/// a list index to a list element.
|
|
651
|
-
///
|
|
652
|
-
/// Example:
|
|
653
|
-
/// ```motoko include=initialize
|
|
654
|
-
/// List.tabulate<Nat>(
|
|
655
|
-
/// 3,
|
|
656
|
-
/// func n { n * 2 }
|
|
657
|
-
/// ) // => ?(0, ?(2, (?4, null)))
|
|
658
|
-
/// ```
|
|
659
|
-
///
|
|
660
|
-
/// Runtime: O(n)
|
|
661
|
-
///
|
|
662
|
-
/// Space: O(n)
|
|
663
|
-
///
|
|
664
|
-
/// *Runtime and space assumes that `f` runs in O(1) time and space.
|
|
665
|
-
public func tabulate<T>(n : Nat, f : Nat -> T) : List<T> {
|
|
666
|
-
var i = 0;
|
|
667
|
-
var l : List<T> = null;
|
|
668
|
-
while (i < n) {
|
|
669
|
-
l := ?(f(i), l);
|
|
670
|
-
i += 1
|
|
671
|
-
};
|
|
672
|
-
reverse(l)
|
|
673
|
-
};
|
|
674
|
-
|
|
675
|
-
/// Create a list with exactly one element.
|
|
676
|
-
///
|
|
677
|
-
/// Example:
|
|
678
|
-
/// ```motoko include=initialize
|
|
679
|
-
/// List.make<Nat>(
|
|
680
|
-
/// 0
|
|
681
|
-
/// ) // => ?(0, null)
|
|
682
|
-
/// ```
|
|
683
|
-
///
|
|
684
|
-
/// Runtime: O(1)
|
|
685
|
-
///
|
|
686
|
-
/// Space: O(1)
|
|
687
|
-
public func make<T>(x : T) : List<T> = ?(x, null);
|
|
688
|
-
|
|
689
|
-
/// Create a list of the given length with the same value in each position.
|
|
690
|
-
///
|
|
691
|
-
/// Example:
|
|
692
|
-
/// ```motoko include=initialize
|
|
693
|
-
/// List.replicate<Nat>(
|
|
694
|
-
/// 3,
|
|
695
|
-
/// 0
|
|
696
|
-
/// ) // => ?(0, ?(0, ?(0, null)))
|
|
697
|
-
/// ```
|
|
698
|
-
///
|
|
699
|
-
/// Runtime: O(n)
|
|
700
|
-
///
|
|
701
|
-
/// Space: O(n)
|
|
702
|
-
public func replicate<T>(n : Nat, x : T) : List<T> {
|
|
703
|
-
var i = 0;
|
|
704
|
-
var l : List<T> = null;
|
|
705
|
-
while (i < n) {
|
|
706
|
-
l := ?(x, l);
|
|
707
|
-
i += 1
|
|
708
|
-
};
|
|
709
|
-
l
|
|
710
|
-
};
|
|
711
|
-
|
|
712
|
-
/// Create a list of pairs from a pair of lists.
|
|
713
|
-
///
|
|
714
|
-
/// If the given lists have different lengths, then the created list will have a
|
|
715
|
-
/// length equal to the length of the smaller list.
|
|
716
|
-
///
|
|
717
|
-
/// Example:
|
|
718
|
-
/// ```motoko include=initialize
|
|
719
|
-
/// List.zip<Nat, Text>(
|
|
720
|
-
/// ?(0, ?(1, ?(2, null))),
|
|
721
|
-
/// ?("0", ?("1", null)),
|
|
722
|
-
/// ) // => ?((0, "0"), ?((1, "1"), null))
|
|
723
|
-
/// ```
|
|
724
|
-
///
|
|
725
|
-
/// Runtime: O(min(size(xs), size(ys)))
|
|
726
|
-
///
|
|
727
|
-
/// Space: O(min(size(xs), size(ys)))
|
|
728
|
-
public func zip<T, U>(xs : List<T>, ys : List<U>) : List<(T, U)> = zipWith<T, U, (T, U)>(xs, ys, func(x, y) { (x, y) });
|
|
729
|
-
|
|
730
|
-
/// Create a list in which elements are created by applying function `f` to each pair `(x, y)` of elements
|
|
731
|
-
/// occuring at the same position in list `xs` and list `ys`.
|
|
732
|
-
///
|
|
733
|
-
/// If the given lists have different lengths, then the created list will have a
|
|
734
|
-
/// length equal to the length of the smaller list.
|
|
735
|
-
///
|
|
736
|
-
/// Example:
|
|
737
|
-
/// ```motoko include=initialize
|
|
738
|
-
/// import Nat = "mo:base/Nat";
|
|
739
|
-
/// import Char = "mo:base/Char";
|
|
740
|
-
///
|
|
741
|
-
/// List.zipWith<Nat, Char, Text>(
|
|
742
|
-
/// ?(0, ?(1, ?(2, null))),
|
|
743
|
-
/// ?('a', ?('b', null)),
|
|
744
|
-
/// func (n, c) { Nat.toText(n) # Char.toText(c) }
|
|
745
|
-
/// ) // => ?("0a", ?("1b", null))
|
|
746
|
-
/// ```
|
|
747
|
-
///
|
|
748
|
-
/// Runtime: O(min(size(xs), size(ys)))
|
|
749
|
-
///
|
|
750
|
-
/// Space: O(min(size(xs), size(ys)))
|
|
751
|
-
///
|
|
752
|
-
/// *Runtime and space assumes that `zip` runs in O(1) time and space.
|
|
753
|
-
public func zipWith<T, U, V>(
|
|
754
|
-
xs : List<T>,
|
|
755
|
-
ys : List<U>,
|
|
756
|
-
f : (T, U) -> V
|
|
757
|
-
) : List<V> {
|
|
758
|
-
switch (pop<T>(xs)) {
|
|
759
|
-
case (null, _) { null };
|
|
760
|
-
case (?x, xt) {
|
|
761
|
-
switch (pop<U>(ys)) {
|
|
762
|
-
case (null, _) { null };
|
|
763
|
-
case (?y, yt) {
|
|
764
|
-
push<V>(f(x, y), zipWith<T, U, V>(xt, yt, f))
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
};
|
|
770
|
-
|
|
771
|
-
/// Split the given list at the given zero-based index.
|
|
772
|
-
///
|
|
773
|
-
/// Example:
|
|
774
|
-
/// ```motoko include=initialize
|
|
775
|
-
/// List.split<Nat>(
|
|
776
|
-
/// 2,
|
|
777
|
-
/// ?(0, ?(1, ?(2, null)))
|
|
778
|
-
/// ) // => (?(0, ?(1, null)), ?(2, null))
|
|
779
|
-
/// ```
|
|
780
|
-
///
|
|
781
|
-
/// Runtime: O(n)
|
|
782
|
-
///
|
|
783
|
-
/// Space: O(n)
|
|
784
|
-
///
|
|
785
|
-
/// *Runtime and space assumes that `zip` runs in O(1) time and space.
|
|
786
|
-
public func split<T>(n : Nat, xs : List<T>) : (List<T>, List<T>) {
|
|
787
|
-
if (n == 0) { (null, xs) } else {
|
|
788
|
-
func rec(n : Nat, xs : List<T>) : (List<T>, List<T>) {
|
|
789
|
-
switch (pop<T>(xs)) {
|
|
790
|
-
case (null, _) { (null, null) };
|
|
791
|
-
case (?h, t) {
|
|
792
|
-
if (n == 1) { (make<T>(h), t) } else {
|
|
793
|
-
let (l, r) = rec(n - 1, t);
|
|
794
|
-
(push<T>(h, l), r)
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
};
|
|
799
|
-
rec(n, xs)
|
|
800
|
-
}
|
|
801
|
-
};
|
|
802
|
-
|
|
803
|
-
/// Split the given list into chunks of length `n`.
|
|
804
|
-
/// The last chunk will be shorter if the length of the given list
|
|
805
|
-
/// does not divide by `n` evenly.
|
|
806
|
-
///
|
|
807
|
-
/// Example:
|
|
808
|
-
/// ```motoko include=initialize
|
|
809
|
-
/// List.chunks<Nat>(
|
|
810
|
-
/// 2,
|
|
811
|
-
/// ?(0, ?(1, ?(2, ?(3, ?(4, null)))))
|
|
812
|
-
/// )
|
|
813
|
-
/// /* => ?(?(0, ?(1, null)),
|
|
814
|
-
/// ?(?(2, ?(3, null)),
|
|
815
|
-
/// ?(?(4, null),
|
|
816
|
-
/// null)))
|
|
817
|
-
/// */
|
|
818
|
-
/// ```
|
|
819
|
-
///
|
|
820
|
-
/// Runtime: O(size)
|
|
821
|
-
///
|
|
822
|
-
/// Space: O(size)
|
|
823
|
-
///
|
|
824
|
-
/// *Runtime and space assumes that `zip` runs in O(1) time and space.
|
|
825
|
-
public func chunks<T>(n : Nat, xs : List<T>) : List<List<T>> {
|
|
826
|
-
let (l, r) = split<T>(n, xs);
|
|
827
|
-
if (isNil<T>(l)) {
|
|
828
|
-
null
|
|
829
|
-
} else {
|
|
830
|
-
push<List<T>>(l, chunks<T>(n, r))
|
|
831
|
-
}
|
|
832
|
-
};
|
|
833
|
-
|
|
834
|
-
/// Convert an array into a list.
|
|
835
|
-
///
|
|
836
|
-
/// Example:
|
|
837
|
-
/// ```motoko include=initialize
|
|
838
|
-
/// List.fromArray<Nat>([ 0, 1, 2, 3, 4])
|
|
839
|
-
/// // => ?(0, ?(1, ?(2, ?(3, ?(4, null)))))
|
|
840
|
-
/// ```
|
|
841
|
-
///
|
|
842
|
-
/// Runtime: O(size)
|
|
843
|
-
///
|
|
844
|
-
/// Space: O(size)
|
|
845
|
-
public func fromArray<T>(xs : [T]) : List<T> {
|
|
846
|
-
Array.foldRight<T, List<T>>(
|
|
847
|
-
xs,
|
|
848
|
-
null,
|
|
849
|
-
func(x : T, ys : List<T>) : List<T> {
|
|
850
|
-
push<T>(x, ys)
|
|
851
|
-
}
|
|
852
|
-
)
|
|
853
|
-
};
|
|
854
|
-
|
|
855
|
-
/// Convert a mutable array into a list.
|
|
856
|
-
///
|
|
857
|
-
/// Example:
|
|
858
|
-
/// ```motoko include=initialize
|
|
859
|
-
/// List.fromVarArray<Nat>([var 0, 1, 2, 3, 4])
|
|
860
|
-
/// // => ?(0, ?(1, ?(2, ?(3, ?(4, null)))))
|
|
861
|
-
/// ```
|
|
862
|
-
///
|
|
863
|
-
/// Runtime: O(size)
|
|
864
|
-
///
|
|
865
|
-
/// Space: O(size)
|
|
866
|
-
public func fromVarArray<T>(xs : [var T]) : List<T> = fromArray<T>(Array.freeze<T>(xs));
|
|
867
|
-
|
|
868
|
-
/// Create an array from a list.
|
|
869
|
-
/// Example:
|
|
870
|
-
/// ```motoko include=initialize
|
|
871
|
-
/// List.toArray<Nat>(?(0, ?(1, ?(2, ?(3, ?(4, null))))))
|
|
872
|
-
/// // => [0, 1, 2, 3, 4]
|
|
873
|
-
/// ```
|
|
874
|
-
///
|
|
875
|
-
/// Runtime: O(size)
|
|
876
|
-
///
|
|
877
|
-
/// Space: O(size)
|
|
878
|
-
public func toArray<T>(xs : List<T>) : [T] {
|
|
879
|
-
let length = size<T>(xs);
|
|
880
|
-
var list = xs;
|
|
881
|
-
Array.tabulate<T>(
|
|
882
|
-
length,
|
|
883
|
-
func(i) {
|
|
884
|
-
let popped = pop<T>(list);
|
|
885
|
-
list := popped.1;
|
|
886
|
-
switch (popped.0) {
|
|
887
|
-
case null { loop { assert false } };
|
|
888
|
-
case (?x) x
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
)
|
|
892
|
-
};
|
|
893
|
-
|
|
894
|
-
/// Create a mutable array from a list.
|
|
895
|
-
/// Example:
|
|
896
|
-
/// ```motoko include=initialize
|
|
897
|
-
/// List.toVarArray<Nat>(?(0, ?(1, ?(2, ?(3, ?(4, null))))))
|
|
898
|
-
/// // => [var 0, 1, 2, 3, 4]
|
|
899
|
-
/// ```
|
|
900
|
-
///
|
|
901
|
-
/// Runtime: O(size)
|
|
902
|
-
///
|
|
903
|
-
/// Space: O(size)
|
|
904
|
-
public func toVarArray<T>(xs : List<T>) : [var T] = Array.thaw<T>(toArray<T>(xs));
|
|
905
|
-
|
|
906
|
-
/// Create an iterator from a list.
|
|
907
|
-
/// Example:
|
|
908
|
-
/// ```motoko include=initialize
|
|
909
|
-
/// var sum = 0;
|
|
910
|
-
/// for (n in List.toIter<Nat>(?(0, ?(1, ?(2, ?(3, ?(4, null))))))) {
|
|
911
|
-
/// sum += n;
|
|
912
|
-
/// };
|
|
913
|
-
/// sum
|
|
914
|
-
/// // => 10
|
|
915
|
-
/// ```
|
|
916
|
-
///
|
|
917
|
-
/// Runtime: O(1)
|
|
918
|
-
///
|
|
919
|
-
/// Space: O(1)
|
|
920
|
-
public func toIter<T>(xs : List<T>) : Iter.Iter<T> {
|
|
921
|
-
var state = xs;
|
|
922
|
-
object {
|
|
923
|
-
public func next() : ?T = switch state {
|
|
924
|
-
case (?(hd, tl)) { state := tl; ?hd };
|
|
925
|
-
case _ null
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
}
|