ic-mops 0.8.5 → 0.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/package.json +3 -1
  2. package/.mops/base@0.7.4/LICENSE +0 -208
  3. package/.mops/base@0.7.4/README.md +0 -64
  4. package/.mops/base@0.7.4/mops.toml +0 -5
  5. package/.mops/base@0.7.4/src/Array.mo +0 -686
  6. package/.mops/base@0.7.4/src/AssocList.mo +0 -203
  7. package/.mops/base@0.7.4/src/Blob.mo +0 -55
  8. package/.mops/base@0.7.4/src/Bool.mo +0 -44
  9. package/.mops/base@0.7.4/src/Buffer.mo +0 -1937
  10. package/.mops/base@0.7.4/src/CertifiedData.mo +0 -29
  11. package/.mops/base@0.7.4/src/Char.mo +0 -67
  12. package/.mops/base@0.7.4/src/Debug.mo +0 -15
  13. package/.mops/base@0.7.4/src/Deque.mo +0 -75
  14. package/.mops/base@0.7.4/src/Error.mo +0 -41
  15. package/.mops/base@0.7.4/src/ExperimentalCycles.mo +0 -51
  16. package/.mops/base@0.7.4/src/ExperimentalInternetComputer.mo +0 -36
  17. package/.mops/base@0.7.4/src/ExperimentalStableMemory.mo +0 -121
  18. package/.mops/base@0.7.4/src/Float.mo +0 -150
  19. package/.mops/base@0.7.4/src/Func.mo +0 -38
  20. package/.mops/base@0.7.4/src/Hash.mo +0 -83
  21. package/.mops/base@0.7.4/src/HashMap.mo +0 -229
  22. package/.mops/base@0.7.4/src/Heap.mo +0 -113
  23. package/.mops/base@0.7.4/src/Int.mo +0 -150
  24. package/.mops/base@0.7.4/src/Int16.mo +0 -159
  25. package/.mops/base@0.7.4/src/Int32.mo +0 -160
  26. package/.mops/base@0.7.4/src/Int64.mo +0 -161
  27. package/.mops/base@0.7.4/src/Int8.mo +0 -160
  28. package/.mops/base@0.7.4/src/Iter.mo +0 -220
  29. package/.mops/base@0.7.4/src/IterType.mo +0 -7
  30. package/.mops/base@0.7.4/src/List.mo +0 -433
  31. package/.mops/base@0.7.4/src/Nat.mo +0 -75
  32. package/.mops/base@0.7.4/src/Nat16.mo +0 -146
  33. package/.mops/base@0.7.4/src/Nat32.mo +0 -146
  34. package/.mops/base@0.7.4/src/Nat64.mo +0 -146
  35. package/.mops/base@0.7.4/src/Nat8.mo +0 -146
  36. package/.mops/base@0.7.4/src/None.mo +0 -19
  37. package/.mops/base@0.7.4/src/Option.mo +0 -160
  38. package/.mops/base@0.7.4/src/Order.mo +0 -46
  39. package/.mops/base@0.7.4/src/Prelude.mo +0 -33
  40. package/.mops/base@0.7.4/src/Principal.mo +0 -58
  41. package/.mops/base@0.7.4/src/RBTree.mo +0 -218
  42. package/.mops/base@0.7.4/src/Random.mo +0 -188
  43. package/.mops/base@0.7.4/src/Result.mo +0 -210
  44. package/.mops/base@0.7.4/src/Stack.mo +0 -40
  45. package/.mops/base@0.7.4/src/Text.mo +0 -615
  46. package/.mops/base@0.7.4/src/Time.mo +0 -37
  47. package/.mops/base@0.7.4/src/Trie.mo +0 -1200
  48. package/.mops/base@0.7.4/src/TrieMap.mo +0 -180
  49. package/.mops/base@0.7.4/src/TrieSet.mo +0 -97
  50. package/.mops/base@0.8.3/LICENSE +0 -208
  51. package/.mops/base@0.8.3/README.md +0 -64
  52. package/.mops/base@0.8.3/mops.toml +0 -6
  53. package/.mops/base@0.8.3/src/Array.mo +0 -717
  54. package/.mops/base@0.8.3/src/AssocList.mo +0 -404
  55. package/.mops/base@0.8.3/src/Blob.mo +0 -212
  56. package/.mops/base@0.8.3/src/Bool.mo +0 -44
  57. package/.mops/base@0.8.3/src/Buffer.mo +0 -2660
  58. package/.mops/base@0.8.3/src/CertifiedData.mo +0 -53
  59. package/.mops/base@0.8.3/src/Char.mo +0 -65
  60. package/.mops/base@0.8.3/src/Debug.mo +0 -56
  61. package/.mops/base@0.8.3/src/Deque.mo +0 -243
  62. package/.mops/base@0.8.3/src/Error.mo +0 -68
  63. package/.mops/base@0.8.3/src/ExperimentalCycles.mo +0 -151
  64. package/.mops/base@0.8.3/src/ExperimentalInternetComputer.mo +0 -60
  65. package/.mops/base@0.8.3/src/ExperimentalStableMemory.mo +0 -348
  66. package/.mops/base@0.8.3/src/Float.mo +0 -843
  67. package/.mops/base@0.8.3/src/Func.mo +0 -46
  68. package/.mops/base@0.8.3/src/Hash.mo +0 -82
  69. package/.mops/base@0.8.3/src/HashMap.mo +0 -457
  70. package/.mops/base@0.8.3/src/Heap.mo +0 -233
  71. package/.mops/base@0.8.3/src/Int.mo +0 -365
  72. package/.mops/base@0.8.3/src/Int16.mo +0 -521
  73. package/.mops/base@0.8.3/src/Int32.mo +0 -522
  74. package/.mops/base@0.8.3/src/Int64.mo +0 -522
  75. package/.mops/base@0.8.3/src/Int8.mo +0 -522
  76. package/.mops/base@0.8.3/src/Iter.mo +0 -227
  77. package/.mops/base@0.8.3/src/IterType.mo +0 -7
  78. package/.mops/base@0.8.3/src/List.mo +0 -930
  79. package/.mops/base@0.8.3/src/Nat.mo +0 -305
  80. package/.mops/base@0.8.3/src/Nat16.mo +0 -144
  81. package/.mops/base@0.8.3/src/Nat32.mo +0 -144
  82. package/.mops/base@0.8.3/src/Nat64.mo +0 -144
  83. package/.mops/base@0.8.3/src/Nat8.mo +0 -144
  84. package/.mops/base@0.8.3/src/None.mo +0 -19
  85. package/.mops/base@0.8.3/src/Option.mo +0 -154
  86. package/.mops/base@0.8.3/src/Order.mo +0 -46
  87. package/.mops/base@0.8.3/src/Prelude.mo +0 -33
  88. package/.mops/base@0.8.3/src/Principal.mo +0 -249
  89. package/.mops/base@0.8.3/src/RBTree.mo +0 -681
  90. package/.mops/base@0.8.3/src/Random.mo +0 -270
  91. package/.mops/base@0.8.3/src/Result.mo +0 -209
  92. package/.mops/base@0.8.3/src/Stack.mo +0 -93
  93. package/.mops/base@0.8.3/src/Text.mo +0 -761
  94. package/.mops/base@0.8.3/src/Time.mo +0 -36
  95. package/.mops/base@0.8.3/src/Timer.mo +0 -62
  96. package/.mops/base@0.8.3/src/Trie.mo +0 -1603
  97. package/.mops/base@0.8.3/src/TrieMap.mo +0 -392
  98. package/.mops/base@0.8.3/src/TrieSet.mo +0 -148
  99. package/network.txt +0 -1
@@ -1,1937 +0,0 @@
1
- /// Class `Buffer<X>` provides a mutable list of elements of type `X`.
2
- /// The class wraps and resizes an underyling array that holds the elements,
3
- /// and thus is comparable to ArrayLists or Vectors in other languages.
4
- ///
5
- /// When required, the current state of a buffer object can be converted to a fixed-size array of its elements.
6
- /// This is recommended for example when storing a buffer to a stable variable.
7
- ///
8
- /// Throughout this documentation, two terms come up that can be confused: `size`
9
- /// and `capacity`. `size` is the length of the list that the buffer represents.
10
- /// `capacity` is the length of the underyling array that backs this list.
11
- /// `capacity` >= `size` is an invariant for this class.
12
- ///
13
- /// Like arrays, elements in the buffer are ordered by indices from 0 to `size`-1.
14
- ///
15
- /// WARNING: Certain operations are amortized O(1) time, such as `add`, but run
16
- /// in worst case O(n) time. These worst case runtimes may exceed the cycles limit
17
- /// per message if the size of the buffer is large enough. Grow these structures
18
- /// with discretion. All amortized operations below also list the worst case runtime.
19
- ///
20
- /// Constructor:
21
- /// The argument `initCapacity` determines the initial capacity of the array.
22
- /// The underlying array grows by a factor of 1.5 when its current capacity is
23
- /// exceeded. Further, when the size of the buffer shrinks to be less than 1/4th
24
- /// of the capacity, the underyling array is shrunk by a factor of 2.
25
- ///
26
- /// Example:
27
- /// ```motoko name=initialize
28
- /// import Buffer "mo:base/Buffer";
29
- ///
30
- /// let buffer = Buffer.Buffer<Nat>(3); // Creates a new Buffer
31
- /// ```
32
- ///
33
- /// Runtime: O(initCapacity)
34
- ///
35
- /// Space: O(initCapacity)
36
-
37
- import Prim "mo:⛔";
38
- import Result "Result";
39
- import Order "Order";
40
- import Array "Array";
41
-
42
- module {
43
- type Order = Order.Order;
44
-
45
- // The following constants are used to manage the capacity.
46
- // The length of `elements` is increased by `INCREASE_FACTOR` when capacity is reached.
47
- // The length of `elements` is decreased by `DECREASE_FACTOR` when capacity is strictly less than
48
- // `DECREASE_THRESHOLD`.
49
-
50
- // INCREASE_FACTOR = INCREASE_FACTOR_NUME / INCREASE_FACTOR_DENOM (with floating point division)
51
- // Keep INCREASE_FACTOR low to minimize cycle limit problem
52
- private let INCREASE_FACTOR_NUME = 3;
53
- private let INCREASE_FACTOR_DENOM = 2;
54
- private let DECREASE_THRESHOLD = 4; // Don't decrease capacity too early to avoid thrashing
55
- private let DECREASE_FACTOR = 2;
56
- private let DEFAULT_CAPACITY = 8;
57
-
58
- private func newCapacity(oldCapacity : Nat) : Nat {
59
- if (oldCapacity == 0) {
60
- 1;
61
- } else {
62
- // calculates ceil(oldCapacity * INCREASE_FACTOR) without floats
63
- ((oldCapacity * INCREASE_FACTOR_NUME) + INCREASE_FACTOR_DENOM - 1) / INCREASE_FACTOR_DENOM;
64
- };
65
- };
66
-
67
- public class Buffer<X>(initCapacity : Nat) = this {
68
- var _size : Nat = 0; // avoid name clash with `size()` method
69
- var elements : [var ?X] = Prim.Array_init(initCapacity, null);
70
-
71
- /// Returns the current number of elements in the buffer.
72
- ///
73
- /// Example:
74
- /// ```motoko include=initialize
75
- /// buffer.size()
76
- /// ```
77
- ///
78
- /// Runtime: O(1)
79
- ///
80
- /// Space: O(1)
81
- public func size() : Nat = _size;
82
-
83
- /// Adds a single element to the end of the buffer, doubling
84
- /// the size of the array if capacity is exceeded.
85
- ///
86
- /// Example:
87
- /// ```motoko include=initialize
88
- ///
89
- /// buffer.add(0); // add 0 to buffer
90
- /// buffer.add(1);
91
- /// buffer.add(2);
92
- /// buffer.add(3); // causes underlying array to increase in capacity
93
- /// Buffer.toArray(buffer)
94
- /// ```
95
- ///
96
- /// Amortized Runtime: O(1), Worst Case Runtime: O(size)
97
- ///
98
- /// Amortized Space: O(1), Worst Case Space: O(size)
99
- public func add(element : X) {
100
- if (_size == elements.size()) {
101
- reserve(newCapacity(elements.size()));
102
- };
103
- elements[_size] := ?element;
104
- _size += 1;
105
- };
106
-
107
- /// Returns the element at index `index`. Traps if `index >= size`. Indexing is zero-based.
108
- ///
109
- /// Example:
110
- /// ```motoko include=initialize
111
- ///
112
- /// buffer.add(10);
113
- /// buffer.add(11);
114
- /// let x = buffer.get(0); // evaluates to 10
115
- /// ```
116
- ///
117
- /// Runtime: O(1)
118
- ///
119
- /// Space: O(1)
120
- public func get(index : Nat) : X {
121
- switch (elements[index]) {
122
- case (?element) element;
123
- case null Prim.trap("Buffer index out of bounds in get");
124
- };
125
- };
126
-
127
- /// Returns the element at index `index` as an option.
128
- /// Returns `null` when `index >= size`. Indexing is zero-based.
129
- ///
130
- /// Example:
131
- /// ```motoko include=initialize
132
- ///
133
- /// buffer.add(10);
134
- /// buffer.add(11);
135
- /// let x = buffer.getOpt(0); // evaluates to ?10
136
- /// let y = buffer.getOpt(2); // evaluates to null
137
- /// ```
138
- ///
139
- /// Runtime: O(1)
140
- ///
141
- /// Space: O(1)
142
- public func getOpt(index : Nat) : ?X {
143
- if (index < _size) {
144
- elements[index];
145
- } else {
146
- null;
147
- };
148
- };
149
-
150
- /// Overwrites the current element at `index` with `element`. Traps if
151
- /// `index` >= size. Indexing is zero-based.
152
- ///
153
- /// Example:
154
- /// ```motoko include=initialize
155
- ///
156
- /// buffer.add(10);
157
- /// buffer.put(0, 20); // overwrites 10 at index 0 with 20
158
- /// Buffer.toArray(buffer)
159
- /// ```
160
- ///
161
- /// Runtime: O(1)
162
- ///
163
- /// Space: O(1)
164
- public func put(index : Nat, element : X) {
165
- if (index >= _size) {
166
- Prim.trap "Buffer index out of bounds in put";
167
- };
168
- elements[index] := ?element;
169
- };
170
-
171
- /// Removes and returns the last item in the buffer or `null` if
172
- /// the buffer is empty.
173
- ///
174
- /// Example:
175
- /// ```motoko include=initialize
176
- ///
177
- /// buffer.add(10);
178
- /// buffer.add(11);
179
- /// let x = buffer.removeLast(); // evaluates to ?11
180
- /// ```
181
- ///
182
- /// Amortized Runtime: O(1), Worst Case Runtime: O(size)
183
- ///
184
- /// Amortized Space: O(1), Worst Case Space: O(size)
185
- public func removeLast() : ?X {
186
- if (_size == 0) {
187
- return null;
188
- };
189
-
190
- _size -= 1;
191
- let lastElement = elements[_size];
192
- elements[_size] := null;
193
-
194
- if (_size < elements.size() / DECREASE_THRESHOLD) {
195
- // FIXME should this new capacity be a function of _size
196
- // instead of the current capacity? E.g. _size * INCREASE_FACTOR
197
- reserve(elements.size() / DECREASE_FACTOR);
198
- };
199
-
200
- lastElement;
201
- };
202
-
203
- /// Removes and returns the element at `index` from the buffer.
204
- /// All elements with index > `index` are shifted one position to the left.
205
- /// This may cause a downsizing of the array.
206
- ///
207
- /// Traps if index >= size.
208
- ///
209
- /// WARNING: Repeated removal of elements using this method is ineffecient
210
- /// and might be a sign that you should consider a different data-structure
211
- /// for your use case.
212
- ///
213
- /// Example:
214
- /// ```motoko include=initialize
215
- ///
216
- /// buffer.add(10);
217
- /// buffer.add(11);
218
- /// buffer.add(12);
219
- /// let x = buffer.remove(1); // evaluates to 11. 11 no longer in list.
220
- /// Buffer.toArray(buffer)
221
- /// ```
222
- ///
223
- /// Runtime: O(size)
224
- ///
225
- /// Amortized Space: O(1), Worst Case Space: O(size)
226
- public func remove(index : Nat) : X {
227
- if (index >= _size) {
228
- Prim.trap "Buffer index out of bounds in remove";
229
- };
230
-
231
- let element = elements[index];
232
-
233
- // copy elements to new array and shift over in one pass
234
- if ((_size - 1) : Nat < elements.size() / DECREASE_THRESHOLD) {
235
- let elements2 = Prim.Array_init<?X>(elements.size() / DECREASE_FACTOR, null);
236
-
237
- var i = 0;
238
- var j = 0;
239
- label l while (i < _size) {
240
- if (i == index) {
241
- i += 1;
242
- continue l;
243
- };
244
-
245
- elements2[j] := elements[i];
246
- i += 1;
247
- j += 1;
248
- };
249
- elements := elements2;
250
- } else {
251
- // just shift over elements
252
- var i = index;
253
- while (i < (_size - 1 : Nat)) {
254
- elements[i] := elements[i + 1];
255
- i += 1;
256
- };
257
- elements[_size - 1] := null;
258
- };
259
-
260
- _size -= 1;
261
-
262
- switch (element) {
263
- case (?element) {
264
- element;
265
- };
266
- case null {
267
- Prim.trap "Malformed buffer in remove";
268
- };
269
- };
270
- };
271
-
272
- /// Resets the buffer. Capacity is set to 8.
273
- ///
274
- /// Example:
275
- /// ```motoko include=initialize
276
- ///
277
- /// buffer.add(10);
278
- /// buffer.add(11);
279
- /// buffer.add(12);
280
- /// buffer.clear(); // buffer is now empty
281
- /// Buffer.toArray(buffer)
282
- /// ```
283
- ///
284
- /// Runtime: O(1)
285
- ///
286
- /// Space: O(1)
287
- public func clear() {
288
- _size := 0;
289
- reserve(DEFAULT_CAPACITY);
290
- };
291
-
292
- /// Removes all elements from the buffer for which the predicate returns false.
293
- /// The predicate is given both the index of the element and the element itself.
294
- /// This may cause a downsizing of the array.
295
- ///
296
- /// Example:
297
- /// ```motoko include=initialize
298
- ///
299
- /// buffer.add(10);
300
- /// buffer.add(11);
301
- /// buffer.add(12);
302
- /// buffer.filterEntries(func(_, x) = x % 2 == 0); // only keep even elements
303
- /// Buffer.toArray(buffer)
304
- /// ```
305
- ///
306
- /// Runtime: O(size)
307
- ///
308
- /// Amortized Space: O(1), Worst Case Space: O(size)
309
- public func filterEntries(predicate : (Nat, X) -> Bool) {
310
- var numRemoved = 0;
311
- let keep = Prim.Array_tabulate<Bool>(
312
- _size,
313
- func i {
314
- switch (elements[i]) {
315
- case (?element) {
316
- if (predicate(i, element)) {
317
- true;
318
- } else {
319
- numRemoved += 1;
320
- false;
321
- };
322
- };
323
- case null {
324
- Prim.trap "Malformed buffer in filter()";
325
- };
326
- };
327
- },
328
- );
329
-
330
- let capacity = elements.size();
331
-
332
- if ((_size - numRemoved : Nat) < capacity / DECREASE_THRESHOLD) {
333
- let elements2 = Prim.Array_init<?X>(capacity / DECREASE_FACTOR, null);
334
-
335
- var i = 0;
336
- var j = 0;
337
- while (i < _size) {
338
- if (keep[i]) {
339
- elements2[j] := elements[i];
340
- i += 1;
341
- j += 1;
342
- } else {
343
- i += 1;
344
- };
345
- };
346
-
347
- elements := elements2;
348
- } else {
349
- var i = 0;
350
- var j = 0;
351
- while (i < _size) {
352
- if (keep[i]) {
353
- elements[j] := elements[i];
354
- i += 1;
355
- j += 1;
356
- } else {
357
- i += 1;
358
- };
359
- };
360
-
361
- while (j < _size) {
362
- elements[j] := null;
363
- j += 1;
364
- };
365
- };
366
-
367
- _size -= numRemoved;
368
- };
369
-
370
- /// Returns the capacity of the buffer (the length of the underlying array).
371
- ///
372
- /// Example:
373
- /// ```motoko include=initialize
374
- ///
375
- /// let buffer = Buffer.Buffer<Nat>(2); // underlying array has capacity 2
376
- /// buffer.add(10);
377
- /// let c1 = buffer.capacity(); // evaluates to 2
378
- /// buffer.add(11);
379
- /// buffer.add(12); // causes capacity to increase by factor of 1.5
380
- /// let c2 = buffer.capacity(); // evaluates to 3
381
- /// ```
382
- ///
383
- /// Runtime: O(1)
384
- ///
385
- /// Space: O(1)
386
- public func capacity() : Nat = elements.size();
387
-
388
- /// Changes the capacity to `capacity`. Traps if `capacity` < `size`.
389
- ///
390
- /// ```motoko include=initialize
391
- ///
392
- /// buffer.reserve(4);
393
- /// buffer.add(10);
394
- /// buffer.add(11);
395
- /// let c = buffer.capacity(); // evaluates to 4
396
- /// ```
397
- ///
398
- /// Runtime: O(capacity)
399
- ///
400
- /// Space: O(capacity)
401
- public func reserve(capacity : Nat) {
402
- if (capacity < _size) {
403
- Prim.trap "capacity must be >= size in reserve";
404
- };
405
-
406
- let elements2 = Prim.Array_init<?X>(capacity, null);
407
-
408
- var i = 0;
409
- while (i < _size) {
410
- elements2[i] := elements[i];
411
- i += 1;
412
- };
413
- elements := elements2;
414
- };
415
-
416
- /// Adds all elements in buffer `b` to this buffer.
417
- ///
418
- /// ```motoko include=initialize
419
- /// let buffer1 = Buffer.Buffer<Nat>(2);
420
- /// let buffer2 = Buffer.Buffer<Nat>(2);
421
- /// buffer1.add(10);
422
- /// buffer1.add(11);
423
- /// buffer2.add(12);
424
- /// buffer2.add(13);
425
- /// buffer1.append(buffer2); // adds elements from buffer2 to buffer1
426
- /// Buffer.toArray(buffer1)
427
- /// ```
428
- ///
429
- /// Amortized Runtime: O(size2), Worst Case Runtime: O(size1 + size2)
430
- ///
431
- /// Amortized Space: O(1), Worst Case Space: O(size1 + size2)
432
- public func append(buffer2 : Buffer<X>) {
433
- let size2 = buffer2.size();
434
- // Make sure you only allocate a new array at most once
435
- if (_size + size2 > elements.size()) {
436
- // FIXME would be nice to have a tabulate for var arrays here
437
- reserve(newCapacity(_size + size2));
438
- };
439
- var i = 0;
440
- while (i < size2) {
441
- elements[_size + i] := buffer2.getOpt i;
442
- i += 1;
443
- };
444
-
445
- _size += size2;
446
- };
447
-
448
- /// Inserts `element` at `index`, shifts all elements to the right of
449
- /// `index` over by one index. Traps if `index` is greater than size.
450
- ///
451
- /// ```motoko include=initialize
452
- /// let buffer1 = Buffer.Buffer<Nat>(2);
453
- /// let buffer2 = Buffer.Buffer<Nat>(2);
454
- /// buffer.add(10);
455
- /// buffer.add(11);
456
- /// buffer.insert(1, 9);
457
- /// Buffer.toArray(buffer)
458
- /// ```
459
- ///
460
- /// Runtime: O(size)
461
- ///
462
- /// Amortized Space: O(1), Worst Case Space: O(size)
463
- public func insert(index : Nat, element : X) {
464
- if (index > _size) {
465
- Prim.trap "Buffer index out of bounds in insert";
466
- };
467
- let capacity = elements.size();
468
-
469
- if (_size + 1 > capacity) {
470
- let capacity = elements.size();
471
- let elements2 = Prim.Array_init<?X>(newCapacity capacity, null);
472
- var i = 0;
473
- while (i < _size + 1) {
474
- if (i < index) {
475
- elements2[i] := elements[i];
476
- } else if (i == index) {
477
- elements2[i] := ?element;
478
- } else {
479
- elements2[i] := elements[i - 1];
480
- };
481
-
482
- i += 1;
483
- };
484
- elements := elements2;
485
- } else {
486
- var i : Nat = _size;
487
- while (i > index) {
488
- elements[i] := elements[i - 1];
489
- i -= 1;
490
- };
491
- elements[index] := ?element;
492
- };
493
-
494
- _size += 1;
495
- };
496
-
497
- /// Inserts `buffer2` at `index`, and shifts all elements to the right of
498
- /// `index` over by size2. Traps if `index` is greater than size.
499
- ///
500
- /// ```motoko include=initialize
501
- /// let buffer1 = Buffer.Buffer<Nat>(2);
502
- /// let buffer2 = Buffer.Buffer<Nat>(2);
503
- /// buffer1.add(10);
504
- /// buffer1.add(11);
505
- /// buffer2.add(12);
506
- /// buffer2.add(13);
507
- /// buffer1.insertBuffer(1, buffer2);
508
- /// Buffer.toArray(buffer1)
509
- /// ```
510
- ///
511
- /// Runtime: O(size)
512
- ///
513
- /// Amortized Space: O(1), Worst Case Space: O(size1 + size2)
514
- public func insertBuffer(index : Nat, buffer2 : Buffer<X>) {
515
- if (index > _size) {
516
- Prim.trap "Buffer index out of bounds in insertBuffer";
517
- };
518
-
519
- let size2 = buffer2.size();
520
- let capacity = elements.size();
521
-
522
- // copy elements to new array and shift over in one pass
523
- if (_size + size2 > capacity) {
524
- let elements2 = Prim.Array_init<?X>(newCapacity(_size + size2), null);
525
- var i = 0;
526
- for (element in elements.vals()) {
527
- if (i == index) {
528
- i += size2;
529
- };
530
- elements2[i] := element;
531
- i += 1;
532
- };
533
-
534
- i := 0;
535
- while (i < size2) {
536
- elements2[i + index] := buffer2.getOpt(i);
537
- i += 1;
538
- };
539
- elements := elements2;
540
- } // just insert
541
- else {
542
- var i = index;
543
- while (i < index + size2) {
544
- if (i < _size) {
545
- elements[i + size2] := elements[i];
546
- };
547
- elements[i] := buffer2.getOpt(i - index);
548
-
549
- i += 1;
550
- };
551
- };
552
-
553
- _size += size2;
554
- };
555
-
556
- /// Sorts the elements in the buffer according to `compare`.
557
- /// Sort is deterministic, stable, and in-place.
558
- ///
559
- /// ```motoko include=initialize
560
- ///
561
- /// import Nat "mo:base/Nat";
562
- ///
563
- /// buffer.add(11);
564
- /// buffer.add(12);
565
- /// buffer.add(10);
566
- /// buffer.sort(Nat.compare);
567
- /// Buffer.toArray(buffer)
568
- /// ```
569
- ///
570
- /// Runtime: O(size * log(size))
571
- ///
572
- /// Space: O(size)
573
- public func sort(compare : (X, X) -> Order.Order) {
574
- // Stable merge sort in a bottom-up iterative style
575
- if (_size == 0) {
576
- return;
577
- };
578
- let scratchSpace = Prim.Array_init<?X>(_size, null);
579
-
580
- let sizeDec = _size - 1 : Nat;
581
- var currSize = 1; // current size of the subarrays being merged
582
- // when the current size == size, the array has been merged into a single sorted array
583
- while (currSize < _size) {
584
- var leftStart = 0; // selects the current left subarray being merged
585
- while (leftStart < sizeDec) {
586
- let mid : Nat = if (leftStart + currSize - 1 : Nat < sizeDec) {
587
- leftStart + currSize - 1;
588
- } else { sizeDec };
589
- let rightEnd : Nat = if (leftStart + (2 * currSize) - 1 : Nat < sizeDec) {
590
- leftStart + (2 * currSize) - 1;
591
- } else { sizeDec };
592
-
593
- // Merge subarrays elements[leftStart...mid] and elements[mid+1...rightEnd]
594
- var left = leftStart;
595
- var right = mid + 1;
596
- var nextSorted = leftStart;
597
- while (left < mid + 1 and right < rightEnd + 1) {
598
- let leftOpt = elements[left];
599
- let rightOpt = elements[right];
600
- switch (leftOpt, rightOpt) {
601
- case (?leftElement, ?rightElement) {
602
- switch (compare(leftElement, rightElement)) {
603
- case (#less or #equal) {
604
- scratchSpace[nextSorted] := leftOpt;
605
- left += 1;
606
- };
607
- case (#greater) {
608
- scratchSpace[nextSorted] := rightOpt;
609
- right += 1;
610
- };
611
- };
612
- };
613
- case (_, _) {
614
- // only sorting non-null items
615
- Prim.trap "Malformed buffer in sort";
616
- };
617
- };
618
- nextSorted += 1;
619
- };
620
- while (left < mid + 1) {
621
- scratchSpace[nextSorted] := elements[left];
622
- nextSorted += 1;
623
- left += 1;
624
- };
625
- while (right < rightEnd + 1) {
626
- scratchSpace[nextSorted] := elements[right];
627
- nextSorted += 1;
628
- right += 1;
629
- };
630
-
631
- // Copy over merged elements
632
- var i = leftStart;
633
- while (i < rightEnd + 1) {
634
- elements[i] := scratchSpace[i];
635
- i += 1;
636
- };
637
-
638
- leftStart += 2 * currSize;
639
- };
640
- currSize *= 2;
641
- };
642
- };
643
-
644
- /// Returns an Iterator (`Iter`) over the elements of this buffer.
645
- /// Iterator provides a single method `next()`, which returns
646
- /// elements in order, or `null` when out of elements to iterate over.
647
- ///
648
- /// ```motoko include=initialize
649
- ///
650
- /// buffer.add(10);
651
- /// buffer.add(11);
652
- /// buffer.add(12);
653
- ///
654
- /// var sum = 0;
655
- /// for (element in buffer.vals()) {
656
- /// sum += element;
657
- /// };
658
- /// sum
659
- /// ```
660
- ///
661
- /// Runtime: O(1)
662
- ///
663
- /// Space: O(1)
664
- public func vals() : { next : () -> ?X } = object {
665
- // FIXME either handle modification to underlying list
666
- // or explicitly warn users in documentation
667
- var nextIndex = 0;
668
- public func next() : ?X {
669
- if (nextIndex >= _size) {
670
- return null;
671
- };
672
- let nextElement = elements[nextIndex];
673
- nextIndex += 1;
674
- nextElement;
675
- };
676
- };
677
-
678
- // FOLLOWING METHODS ARE DEPRECATED
679
-
680
- /// @deprecated Use static library function instead.
681
- public func clone() : Buffer<X> {
682
- let newBuffer = Buffer<X>(elements.size());
683
- for (element in vals()) {
684
- newBuffer.add(element);
685
- };
686
- newBuffer;
687
- };
688
-
689
- /// @deprecated Use static library function instead.
690
- public func toArray() : [X] =
691
- // immutable clone of array
692
- Prim.Array_tabulate<X>(
693
- _size,
694
- func(i : Nat) : X { get i },
695
- );
696
-
697
- /// @deprecated Use static library function instead.
698
- public func toVarArray() : [var X] {
699
- if (_size == 0) { [var] } else {
700
- let newArray = Prim.Array_init<X>(_size, get 0);
701
- var i = 0;
702
- for (element in vals()) {
703
- newArray[i] := element;
704
- i += 1;
705
- };
706
- newArray;
707
- };
708
- };
709
- };
710
-
711
- /// Returns true iff the buffer is empty.
712
- ///
713
- /// Runtime: O(1)
714
- ///
715
- /// Space: O(1)
716
- public func isEmpty<X>(buffer : Buffer<X>) : Bool = buffer.size() == 0;
717
-
718
- /// Returns true iff `buffer` contains `element` with respect to equality
719
- /// defined by `equal`.
720
- ///
721
- /// Runtime: O(size)
722
- ///
723
- /// Space: O(1)
724
- ///
725
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
726
- public func contains<X>(buffer : Buffer<X>, element : X, equal : (X, X) -> Bool) : Bool {
727
- for (current in buffer.vals()) {
728
- if (equal(current, element)) {
729
- return true;
730
- };
731
- };
732
-
733
- false;
734
- };
735
-
736
- /// Returns a copy of `buffer`, with the same capacity.
737
- ///
738
- /// Runtime: O(size)
739
- ///
740
- /// Space: O(size)
741
- public func clone<X>(buffer : Buffer<X>) : Buffer<X> {
742
- let newBuffer = Buffer<X>(buffer.capacity());
743
- for (element in buffer.vals()) {
744
- newBuffer.add(element);
745
- };
746
- newBuffer;
747
- };
748
-
749
- /// Finds the greatest element in `buffer` defined by `compare`.
750
- /// Returns `null` if `buffer` is empty.
751
- ///
752
- /// Runtime: O(size)
753
- ///
754
- /// Space: O(1)
755
- ///
756
- /// *Runtime and space assumes that `compare` runs in O(1) time and space.
757
- public func max<X>(buffer : Buffer<X>, compare : (X, X) -> Order) : ?X {
758
- if (buffer.size() == 0) {
759
- return null;
760
- };
761
-
762
- var maxSoFar = buffer.get(0);
763
- for (current in buffer.vals()) {
764
- switch (compare(current, maxSoFar)) {
765
- case (#greater) {
766
- maxSoFar := current;
767
- };
768
- case _ {};
769
- };
770
- };
771
-
772
- ?maxSoFar;
773
- };
774
-
775
- /// Finds the least element in `buffer` defined by `compare`.
776
- /// Returns `null` if `buffer` is empty.
777
- ///
778
- /// Runtime: O(size)
779
- ///
780
- /// Space: O(1)
781
- ///
782
- /// *Runtime and space assumes that `compare` runs in O(1) time and space.
783
- public func min<X>(buffer : Buffer<X>, compare : (X, X) -> Order) : ?X {
784
- if (buffer.size() == 0) {
785
- return null;
786
- };
787
-
788
- var minSoFar = buffer.get(0);
789
- for (current in buffer.vals()) {
790
- switch (compare(current, minSoFar)) {
791
- case (#less) {
792
- minSoFar := current;
793
- };
794
- case _ {};
795
- };
796
- };
797
-
798
- ?minSoFar;
799
- };
800
-
801
- /// Defines equality for two buffers, using `equal` to recursively compare elements in the
802
- /// buffers. Returns true iff the two buffers are of the same size, and `equal`
803
- /// evaluates to true for every pair of elements in the two buffers of the same
804
- /// index.
805
- ///
806
- /// Runtime: O(size)
807
- ///
808
- /// Space: O(1)
809
- ///
810
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
811
- public func equal<X>(buffer1 : Buffer<X>, buffer2 : Buffer<X>, equal : (X, X) -> Bool) : Bool {
812
- let size1 = buffer1.size();
813
-
814
- if (size1 != buffer2.size()) {
815
- return false;
816
- };
817
-
818
- var i = 0;
819
- while (i < size1) {
820
- if (not equal(buffer1.get(i), buffer2.get(i))) {
821
- return false;
822
- };
823
- i += 1;
824
- };
825
-
826
- true;
827
- };
828
-
829
- /// Defines comparison for two buffers, using `compare` to recursively compare elements in the
830
- /// buffers. Comparison is defined lexicographically.
831
- ///
832
- /// Runtime: O(size)
833
- ///
834
- /// Space: O(1)
835
- ///
836
- /// *Runtime and space assumes that `compare` runs in O(1) time and space.
837
- public func compare<X>(buffer1 : Buffer<X>, buffer2 : Buffer<X>, compare : (X, X) -> Order.Order) : Order.Order {
838
- let size1 = buffer1.size();
839
- let size2 = buffer2.size();
840
- let minSize = if (size1 < size2) { size1 } else { size2 };
841
-
842
- var i = 0;
843
- while (i < minSize) {
844
- switch (compare(buffer1.get(i), buffer2.get(i))) {
845
- case (#less) {
846
- return #less;
847
- };
848
- case (#greater) {
849
- return #greater;
850
- };
851
- case _ {};
852
- };
853
- i += 1;
854
- };
855
-
856
- if (size1 < size2) {
857
- #less;
858
- } else if (size1 == size2) {
859
- #equal;
860
- } else {
861
- #greater;
862
- };
863
- };
864
-
865
- /// Creates a textual representation of `buffer`, using `toText` to recursively
866
- /// convert the elements into Text.
867
- ///
868
- /// Runtime: O(size)
869
- ///
870
- /// Space: O(size)
871
- ///
872
- /// *Runtime and space assumes that `toText` runs in O(1) time and space.
873
- public func toText<X>(buffer : Buffer<X>, toText : X -> Text) : Text {
874
- let size : Int = buffer.size();
875
- var i = 0;
876
- var text = "";
877
- while (i < size - 1) {
878
- text := text # toText(buffer.get(i)) # ", "; // Text implemented as rope
879
- i += 1;
880
- };
881
- if (size > 0) {
882
- // avoid the trailing comma
883
- text := text # toText(buffer.get(i));
884
- };
885
-
886
- "[" # text # "]";
887
- };
888
-
889
- /// Hashes `buffer` using `hash` to hash the underlying elements.
890
- /// The deterministic hash function is a function of the elements in the Buffer, as well
891
- /// as their ordering.
892
- ///
893
- /// Runtime: O(size)
894
- ///
895
- /// Space: O(1)
896
- ///
897
- /// *Runtime and space assumes that `hash` runs in O(1) time and space.
898
- public func hash<X>(buffer : Buffer<X>, hash : X -> Nat32) : Nat32 {
899
- let size = buffer.size();
900
- var i = 0;
901
- var accHash : Nat32 = 0;
902
-
903
- while (i < size) {
904
- accHash := Prim.intToNat32Wrap(i) ^ accHash ^ hash(buffer.get(i));
905
- i += 1;
906
- };
907
-
908
- accHash;
909
- };
910
-
911
- /// Finds the first index of `element` in `buffer` using equality of elements defined
912
- /// by `equal`. Returns `null` if `element` is not found.
913
- ///
914
- /// Runtime: O(size)
915
- ///
916
- /// Space: O(size)
917
- ///
918
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
919
- public func indexOf<X>(element : X, buffer : Buffer<X>, equal : (X, X) -> Bool) : ?Nat {
920
- let size = buffer.size();
921
- var i = 0;
922
- while (i < size) {
923
- if (equal(buffer.get(i), element)) {
924
- return ?i;
925
- };
926
- i += 1;
927
- };
928
-
929
- null;
930
- };
931
-
932
- /// Finds the last index of `element` in `buffer` using equality of elements defined
933
- /// by `equal`. Returns `null` if `element` is not found.
934
- ///
935
- /// Runtime: O(size)
936
- ///
937
- /// Space: O(size)
938
- ///
939
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
940
- public func lastIndexOf<X>(element : X, buffer : Buffer<X>, equal : (X, X) -> Bool) : ?Nat {
941
- let size = buffer.size();
942
- if (size == 0) {
943
- return null;
944
- };
945
- var i = size;
946
- while (i >= 1) {
947
- i -= 1;
948
- if (equal(buffer.get(i), element)) {
949
- return ?i;
950
- };
951
- };
952
-
953
- null;
954
- };
955
-
956
- /// Searches for `subBuffer` in `buffer`, and returns the starting index if it is found.
957
- ///
958
- /// Runtime: O(size of buffer + size of subBuffer)
959
- ///
960
- /// Space: O(size of subBuffer)
961
- ///
962
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
963
- public func indexOfBuffer<X>(subBuffer : Buffer<X>, buffer : Buffer<X>, equal : (X, X) -> Bool) : ?Nat {
964
- // Uses the KMP substring search algorithm
965
- // Implementation from: https://www.educative.io/answers/what-is-the-knuth-morris-pratt-algorithm
966
- let size = buffer.size();
967
- let subSize = subBuffer.size();
968
- if (subSize > size or subSize == 0) {
969
- return null;
970
- };
971
-
972
- // precompute lps
973
- let lps = Prim.Array_init<Nat>(subSize, 0);
974
- var i = 0;
975
- var j = 1;
976
-
977
- while (j < subSize) {
978
- if (equal(subBuffer.get(i), subBuffer.get(j))) {
979
- i += 1;
980
- lps[j] := i;
981
- j += 1;
982
- } else if (i == 0) {
983
- lps[j] := 0;
984
- j += 1;
985
- } else {
986
- i := lps[i - 1];
987
- };
988
- };
989
-
990
- // start search
991
- i := 0;
992
- j := 0;
993
- let subSizeDec = subSize - 1 : Nat; // hoisting loop invariant
994
- while (i < subSize and j < size) {
995
- if (equal(subBuffer.get(i), buffer.get(j)) and i == subSizeDec) {
996
- return ?(j - i);
997
- } else if (equal(subBuffer.get(i), buffer.get(j))) {
998
- i += 1;
999
- j += 1;
1000
- } else {
1001
- if (i != 0) {
1002
- i := lps[i - 1];
1003
- } else {
1004
- j += 1;
1005
- };
1006
- };
1007
- };
1008
-
1009
- null;
1010
- };
1011
-
1012
- /// Similar to indexOf, but runs in logarithmic time. Assumes that `buffer` is sorted.
1013
- /// Behavior is undefined if `buffer` is not sorted. Uses `compare` to
1014
- /// perform the search. Returns an index of `element` if it is found.
1015
- ///
1016
- /// Runtime: O(log(size))
1017
- ///
1018
- /// Space: O(1)
1019
- ///
1020
- /// *Runtime and space assumes that `compare` runs in O(1) time and space.
1021
- public func binarySearch<X>(element : X, buffer : Buffer<X>, compare : (X, X) -> Order.Order) : ?Nat {
1022
- var low = 0;
1023
- var high = buffer.size();
1024
-
1025
- while (low < high) {
1026
- let mid = (low + high) / 2;
1027
- let current = buffer.get(mid);
1028
- switch (compare(element, current)) {
1029
- case (#equal) {
1030
- return ?mid;
1031
- };
1032
- case (#less) {
1033
- high := mid;
1034
- };
1035
- case (#greater) {
1036
- low := mid + 1;
1037
- };
1038
- };
1039
- };
1040
-
1041
- null;
1042
- };
1043
-
1044
- /// Returns the sub-buffer of `buffer` starting at index `start`
1045
- /// of length `length`. Traps if `start` is out of bounds, or `start + length`
1046
- /// is greater than the size of `buffer`.
1047
- ///
1048
- /// Runtime: O(length)
1049
- ///
1050
- /// Space: O(length)
1051
- public func subBuffer<X>(buffer : Buffer<X>, start : Nat, length : Nat) : Buffer<X> {
1052
- let size = buffer.size();
1053
- let end = start + length; // exclusive
1054
- if (start >= size or end > size) {
1055
- Prim.trap "Buffer index out of bounds in subBuffer";
1056
- };
1057
-
1058
- let newBuffer = Buffer<X>(newCapacity length);
1059
-
1060
- var i = start;
1061
- while (i < end) {
1062
- newBuffer.add(buffer.get(i));
1063
-
1064
- i += 1;
1065
- };
1066
-
1067
- newBuffer;
1068
- };
1069
-
1070
- /// Checks if `subBuffer` is a sub-Buffer of `buffer`. Uses `equal` to
1071
- /// compare elements.
1072
- ///
1073
- /// Runtime: O(size of subBuffer + size of buffer)
1074
- ///
1075
- /// Space: O(size of subBuffer)
1076
- ///
1077
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
1078
- public func isSubBufferOf<X>(subBuffer : Buffer<X>, buffer : Buffer<X>, equal : (X, X) -> Bool) : Bool {
1079
- switch (indexOfBuffer(subBuffer, buffer, equal)) {
1080
- case null subBuffer.size() == 0;
1081
- case _ true;
1082
- };
1083
- };
1084
-
1085
- /// Checks if `subBuffer` is a strict subBuffer of `buffer`, i.e. `subBuffer` must be
1086
- /// strictly contained inside both the first and last indices of `buffer`.
1087
- /// Uses `equal` to compare elements.
1088
- ///
1089
- /// Runtime: O(size of subBuffer + size of buffer)
1090
- ///
1091
- /// Space: O(size of subBuffer)
1092
- ///
1093
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
1094
- public func isStrictSubBufferOf<X>(subBuffer : Buffer<X>, buffer : Buffer<X>, equal : (X, X) -> Bool) : Bool {
1095
- let subBufferSize = subBuffer.size();
1096
-
1097
- switch (indexOfBuffer(subBuffer, buffer, equal)) {
1098
- case (?index) {
1099
- index != 0 and index != (buffer.size() - subBufferSize : Nat) // enforce strictness
1100
- };
1101
- case null {
1102
- subBufferSize == 0 and subBufferSize != buffer.size();
1103
- };
1104
- };
1105
- };
1106
-
1107
- /// Returns the prefix of `buffer` of length `length`. Traps if `length`
1108
- /// is greater than the size of `buffer`.
1109
- ///
1110
- /// Runtime: O(length)
1111
- ///
1112
- /// Space: O(length)
1113
- public func prefix<X>(buffer : Buffer<X>, length : Nat) : Buffer<X> {
1114
- let size = buffer.size();
1115
- if (length > size) {
1116
- Prim.trap "Buffer index out of bounds in prefix";
1117
- };
1118
-
1119
- let newBuffer = Buffer<X>(newCapacity length);
1120
-
1121
- var i = 0;
1122
- while (i < length) {
1123
- newBuffer.add(buffer.get(i));
1124
- i += 1;
1125
- };
1126
-
1127
- newBuffer;
1128
- };
1129
-
1130
- /// Checks if `prefix` is a prefix of `buffer`. Uses `equal` to
1131
- /// compare elements.
1132
- ///
1133
- /// Runtime: O(size of prefix)
1134
- ///
1135
- /// Space: O(size of prefix)
1136
- ///
1137
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
1138
- public func isPrefixOf<X>(prefix : Buffer<X>, buffer : Buffer<X>, equal : (X, X) -> Bool) : Bool {
1139
- let sizePrefix = prefix.size();
1140
- if (buffer.size() < sizePrefix) {
1141
- return false;
1142
- };
1143
-
1144
- var i = 0;
1145
- while (i < sizePrefix) {
1146
- if (not equal(buffer.get(i), prefix.get(i))) {
1147
- return false;
1148
- };
1149
-
1150
- i += 1;
1151
- };
1152
-
1153
- return true;
1154
- };
1155
-
1156
- /// Checks if `prefix` is a strict prefix of `buffer`. Uses `equal` to
1157
- /// compare elements.
1158
- ///
1159
- /// Runtime: O(size of prefix)
1160
- ///
1161
- /// Space: O(size of prefix)
1162
- ///
1163
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
1164
- public func isStrictPrefixOf<X>(prefix : Buffer<X>, buffer : Buffer<X>, equal : (X, X) -> Bool) : Bool {
1165
- if (buffer.size() <= prefix.size()) {
1166
- return false;
1167
- };
1168
- isPrefixOf(prefix, buffer, equal);
1169
- };
1170
-
1171
- /// Returns the suffix of `buffer` of length `length`.
1172
- /// Traps if `length`is greater than the size of `buffer`.
1173
- ///
1174
- /// Runtime: O(length)
1175
- ///
1176
- /// Space: O(length)
1177
- public func suffix<X>(buffer : Buffer<X>, length : Nat) : Buffer<X> {
1178
- let size = buffer.size();
1179
-
1180
- if (length > size) {
1181
- Prim.trap "Buffer index out of bounds in suffix";
1182
- };
1183
-
1184
- let newBuffer = Buffer<X>(newCapacity length);
1185
-
1186
- var i = size - length : Nat;
1187
- while (i < size) {
1188
- newBuffer.add(buffer.get(i));
1189
-
1190
- i += 1;
1191
- };
1192
-
1193
- newBuffer;
1194
- };
1195
-
1196
- /// Checks if `suffix` is a suffix of `buffer`. Uses `equal` to compare
1197
- /// elements.
1198
- ///
1199
- /// Runtime: O(length of suffix)
1200
- ///
1201
- /// Space: O(length of suffix)
1202
- ///
1203
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
1204
- public func isSuffixOf<X>(suffix : Buffer<X>, buffer : Buffer<X>, equal : (X, X) -> Bool) : Bool {
1205
- let suffixSize = suffix.size();
1206
- let bufferSize = buffer.size();
1207
- if (bufferSize < suffixSize) {
1208
- return false;
1209
- };
1210
-
1211
- var i = bufferSize;
1212
- var j = suffixSize;
1213
- while (i >= 1 and j >= 1) {
1214
- i -= 1;
1215
- j -= 1;
1216
- if (not equal(buffer.get(i), suffix.get(j))) {
1217
- return false;
1218
- };
1219
- };
1220
-
1221
- return true;
1222
- };
1223
-
1224
- /// Checks if `suffix` is a strict suffix of `buffer`. Uses `equal` to compare
1225
- /// elements.
1226
- ///
1227
- /// Runtime: O(length of suffix)
1228
- ///
1229
- /// Space: O(length of suffix)
1230
- ///
1231
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
1232
- public func isStrictSuffixOf<X>(suffix : Buffer<X>, buffer : Buffer<X>, equal : (X, X) -> Bool) : Bool {
1233
- if (buffer.size() <= suffix.size()) {
1234
- return false;
1235
- };
1236
- isSuffixOf(suffix, buffer, equal);
1237
- };
1238
-
1239
- /// Returns true iff every element in `buffer` satisfies `predicate`.
1240
- ///
1241
- /// Runtime: O(size)
1242
- ///
1243
- /// Space: O(1)
1244
- ///
1245
- /// *Runtime and space assumes that `predicate` runs in O(1) time and space.
1246
- public func forAll<X>(buffer : Buffer<X>, predicate : X -> Bool) : Bool {
1247
- for (element in buffer.vals()) {
1248
- if (not predicate element) {
1249
- return false;
1250
- };
1251
- };
1252
-
1253
- true;
1254
- };
1255
-
1256
- /// Returns true iff some element in `buffer` satisfies `predicate`.
1257
- ///
1258
- /// Runtime: O(size)
1259
- ///
1260
- /// Space: O(1)
1261
- ///
1262
- /// *Runtime and space assumes that `predicate` runs in O(1) time and space.
1263
- public func forSome<X>(buffer : Buffer<X>, predicate : X -> Bool) : Bool {
1264
- for (element in buffer.vals()) {
1265
- if (predicate element) {
1266
- return true;
1267
- };
1268
- };
1269
-
1270
- false;
1271
- };
1272
-
1273
- /// Returns true iff no element in `buffer` satisfies `predicate`.
1274
- ///
1275
- /// Runtime: O(size)
1276
- ///
1277
- /// Space: O(1)
1278
- ///
1279
- /// *Runtime and space assumes that `predicate` runs in O(1) time and space.
1280
- public func forNone<X>(buffer : Buffer<X>, predicate : X -> Bool) : Bool {
1281
- for (element in buffer.vals()) {
1282
- if (predicate element) {
1283
- return false;
1284
- };
1285
- };
1286
-
1287
- true;
1288
- };
1289
-
1290
- /// Creates an array containing elements from `buffer`.
1291
- ///
1292
- /// Runtime: O(size)
1293
- ///
1294
- /// Space: O(size)
1295
- public func toArray<X>(buffer : Buffer<X>) : [X] =
1296
- // immutable clone of array
1297
- Prim.Array_tabulate<X>(
1298
- buffer.size(),
1299
- func(i : Nat) : X { buffer.get(i) },
1300
- );
1301
-
1302
- /// Creates a mutable array containing elements from `buffer`.
1303
- ///
1304
- /// Runtime: O(size)
1305
- ///
1306
- /// Space: O(size)
1307
- public func toVarArray<X>(buffer : Buffer<X>) : [var X] {
1308
- let size = buffer.size();
1309
- if (size == 0) { [var] } else {
1310
- let newArray = Prim.Array_init<X>(size, buffer.get(0));
1311
- var i = 1;
1312
- while (i < size) {
1313
- newArray[i] := buffer.get(i);
1314
- i += 1;
1315
- };
1316
- newArray;
1317
- };
1318
- };
1319
-
1320
- /// Creates a buffer containing elements from `array`.
1321
- ///
1322
- /// Runtime: O(size)
1323
- ///
1324
- /// Space: O(size)
1325
- public func fromArray<X>(array : [X]) : Buffer<X> {
1326
- // When returning new buffer, if possible, set the capacity
1327
- // to the capacity of the old buffer. Otherwise, return them
1328
- // at 2/3 capacity (like in this case). Alternative is to
1329
- // calculate what the size would be if the elements were
1330
- // sequentially added using `add`. This current strategy (2/3)
1331
- // is the upper bound of that calculation (if the last element
1332
- // added caused a capacity increase).
1333
- let newBuffer = Buffer<X>(newCapacity(array.size()));
1334
-
1335
- for (element in array.vals()) {
1336
- newBuffer.add(element);
1337
- };
1338
-
1339
- newBuffer;
1340
- };
1341
-
1342
- /// Creates a buffer containing elements from `array`.
1343
- ///
1344
- /// Runtime: O(size)
1345
- ///
1346
- /// Space: O(size)
1347
- public func fromVarArray<X>(array : [var X]) : Buffer<X> {
1348
- let newBuffer = Buffer<X>(newCapacity(array.size()));
1349
-
1350
- for (element in array.vals()) {
1351
- newBuffer.add(element);
1352
- };
1353
-
1354
- newBuffer;
1355
- };
1356
-
1357
- /// Creates a buffer containing elements from `iter`.
1358
- ///
1359
- /// Runtime: O(size)
1360
- ///
1361
- /// Space: O(size)
1362
- public func fromIter<X>(iter : { next : () -> ?X }) : Buffer<X> {
1363
- let newBuffer = Buffer<X>(DEFAULT_CAPACITY); // can't get size from `iter`
1364
-
1365
- for (element in iter) {
1366
- newBuffer.add(element);
1367
- };
1368
-
1369
- newBuffer;
1370
- };
1371
-
1372
- /// Reallocates the array underlying `buffer` such that capacity == size.
1373
- ///
1374
- /// Runtime: O(size)
1375
- ///
1376
- /// Space: O(size)
1377
- public func trimToSize<X>(buffer : Buffer<X>) {
1378
- let size = buffer.size();
1379
- if (size < buffer.capacity()) {
1380
- buffer.reserve(size);
1381
- };
1382
- };
1383
-
1384
- /// Creates a new buffer by applying `f` to each element in `buffer`.
1385
- ///
1386
- /// Runtime: O(size)
1387
- ///
1388
- /// Space: O(size)
1389
- ///
1390
- /// *Runtime and space assumes that `f` runs in O(1) time and space.
1391
- public func map<X, Y>(buffer : Buffer<X>, f : X -> Y) : Buffer<Y> {
1392
- let newBuffer = Buffer<Y>(buffer.capacity());
1393
-
1394
- for (element in buffer.vals()) {
1395
- newBuffer.add(f element);
1396
- };
1397
-
1398
- newBuffer;
1399
- };
1400
-
1401
- /// Applies `f` to each element in `buffer`.
1402
- ///
1403
- /// Runtime: O(size)
1404
- ///
1405
- /// Space: O(size)
1406
- ///
1407
- /// *Runtime and space assumes that `f` runs in O(1) time and space.
1408
- public func iterate<X>(buffer : Buffer<X>, f : X -> ()) {
1409
- for (element in buffer.vals()) {
1410
- f element;
1411
- };
1412
- };
1413
-
1414
- /// Applies `f` to each element in `buffer` and its index.
1415
- ///
1416
- /// Runtime: O(size)
1417
- ///
1418
- /// Space: O(size)
1419
- ///
1420
- /// *Runtime and space assumes that `f` runs in O(1) time and space.
1421
- public func mapEntries<X, Y>(buffer : Buffer<X>, f : (Nat, X) -> Y) : Buffer<Y> {
1422
- let newBuffer = Buffer<Y>(buffer.capacity());
1423
-
1424
- var i = 0;
1425
- let size = buffer.size();
1426
- while (i < size) {
1427
- newBuffer.add(f(i, buffer.get(i)));
1428
- i += 1;
1429
- };
1430
-
1431
- newBuffer;
1432
- };
1433
-
1434
- /// Creates a new buffer by applying `f` to each element in `buffer`,
1435
- /// and keeping all non-null elements.
1436
- ///
1437
- /// Runtime: O(size)
1438
- ///
1439
- /// Space: O(size)
1440
- ///
1441
- /// *Runtime and space assumes that `f` runs in O(1) time and space.
1442
- public func mapFilter<X, Y>(buffer : Buffer<X>, f : X -> ?Y) : Buffer<Y> {
1443
- let newBuffer = Buffer<Y>(buffer.capacity());
1444
-
1445
- for (element in buffer.vals()) {
1446
- switch (f element) {
1447
- case (?element) {
1448
- newBuffer.add(element);
1449
- };
1450
- case _ {};
1451
- };
1452
- };
1453
-
1454
- newBuffer;
1455
- };
1456
-
1457
- /// Creates a new buffer by applying `f` to each element in `buffer`.
1458
- /// If any invocation of `f` produces an `#err`, returns an `#err`. Otherwise
1459
- /// Returns an `#ok` containing the new buffer.
1460
- ///
1461
- /// Runtime: O(size)
1462
- ///
1463
- /// Space: O(size)
1464
- ///
1465
- /// *Runtime and space assumes that `f` runs in O(1) time and space.
1466
- public func mapResult<X, Y, E>(buffer : Buffer<X>, f : X -> Result.Result<Y, E>) : Result.Result<Buffer<Y>, E> {
1467
- let newBuffer = Buffer<Y>(buffer.capacity());
1468
-
1469
- for (element in buffer.vals()) {
1470
- switch (f element) {
1471
- case (#ok result) {
1472
- newBuffer.add(result);
1473
- };
1474
- case (#err e) {
1475
- return #err e;
1476
- };
1477
- };
1478
- };
1479
-
1480
- #ok newBuffer;
1481
- };
1482
-
1483
- /// Creates a new buffer by applying `k` to each element in `buffer`,
1484
- /// and concatenating the resulting buffers in order. This operation
1485
- /// is similar to what in other functional languages is known as monadic bind.
1486
- ///
1487
- /// Runtime: O(size)
1488
- ///
1489
- /// Space: O(size)
1490
- ///
1491
- /// *Runtime and space assumes that `k` runs in O(1) time and space.
1492
- public func chain<X, Y>(buffer : Buffer<X>, k : X -> Buffer<Y>) : Buffer<Y> {
1493
- let newBuffer = Buffer<Y>(buffer.size() * 4);
1494
-
1495
- for (element in buffer.vals()) {
1496
- newBuffer.append(k element);
1497
- };
1498
-
1499
- newBuffer;
1500
- };
1501
-
1502
- /// Collapses the elements in `buffer` into a single value by starting with `base`
1503
- /// and progessively combining elements into `base` with `combine`. Iteration runs
1504
- /// left to right.
1505
- ///
1506
- /// Runtime: O(size)
1507
- ///
1508
- /// Space: O(1)
1509
- ///
1510
- /// *Runtime and space assumes that `combine` runs in O(1) time and space.
1511
- public func foldLeft<A, X>(buffer : Buffer<X>, base : A, combine : (A, X) -> A) : A {
1512
- var accumulation = base;
1513
-
1514
- for (element in buffer.vals()) {
1515
- accumulation := combine(accumulation, element);
1516
- };
1517
-
1518
- accumulation;
1519
- };
1520
-
1521
- /// Collapses the elements in `buffer` into a single value by starting with `base`
1522
- /// and progessively combining elements into `base` with `combine`. Iteration runs
1523
- /// right to left.
1524
- ///
1525
- /// Runtime: O(size)
1526
- ///
1527
- /// Space: O(1)
1528
- ///
1529
- /// *Runtime and space assumes that `combine` runs in O(1) time and space.
1530
- public func foldRight<X, A>(buffer : Buffer<X>, base : A, combine : (X, A) -> A) : A {
1531
- let size = buffer.size();
1532
- if (size == 0) {
1533
- return base;
1534
- };
1535
- var accumulation = base;
1536
-
1537
- var i = size;
1538
- while (i >= 1) {
1539
- i -= 1; // to avoid Nat underflow, subtract first and stop iteration at 1
1540
- accumulation := combine(buffer.get(i), accumulation);
1541
- };
1542
-
1543
- accumulation;
1544
- };
1545
-
1546
- /// Returns the first element of `buffer`. Traps if `buffer` is empty.
1547
- ///
1548
- /// Runtime: O(1)
1549
- ///
1550
- /// Space: O(1)
1551
- public func first<X>(buffer : Buffer<X>) : X = buffer.get(0);
1552
-
1553
- /// Returns the last element of `buffer`. Traps if `buffer` is empty.
1554
- ///
1555
- /// Runtime: O(1)
1556
- ///
1557
- /// Space: O(1)
1558
- public func last<X>(buffer : Buffer<X>) : X = buffer.get(buffer.size() - 1);
1559
-
1560
- /// Returns a new buffer with capacity and size 1, containing `element`.
1561
- ///
1562
- /// Runtime: O(1)
1563
- ///
1564
- /// Space: O(1)
1565
- public func make<X>(element : X) : Buffer<X> {
1566
- let newBuffer = Buffer<X>(1);
1567
- newBuffer.add(element);
1568
- newBuffer;
1569
- };
1570
-
1571
- /// Reverses the order of elements in `buffer`.
1572
- ///
1573
- /// Runtime: O(size)
1574
- ///
1575
- /// Space: O(1)
1576
- public func reverse<X>(buffer : Buffer<X>) {
1577
- let size = buffer.size();
1578
- if (size == 0) {
1579
- return;
1580
- };
1581
-
1582
- var i = 0;
1583
- var j = size - 1 : Nat;
1584
- var temp = buffer.get(0);
1585
- while (i < size / 2) {
1586
- temp := buffer.get(j);
1587
- buffer.put(j, buffer.get(i));
1588
- buffer.put(i, temp);
1589
- i += 1;
1590
- j -= 1;
1591
- };
1592
- };
1593
-
1594
- /// Merges two sorted buffers into a single sorted buffer, using `compare` to define
1595
- /// the ordering. The final ordering is stable. Behavior is undefined if either
1596
- /// `buffer1` or `buffer2` is not sorted.
1597
- ///
1598
- /// Runtime: O(size1 + size2)
1599
- ///
1600
- /// Space: O(size1 + size2)
1601
- ///
1602
- /// *Runtime and space assumes that `compare` runs in O(1) time and space.
1603
- public func merge<X>(buffer1 : Buffer<X>, buffer2 : Buffer<X>, compare : (X, X) -> Order) : Buffer<X> {
1604
- let size1 = buffer1.size();
1605
- let size2 = buffer2.size();
1606
-
1607
- let newBuffer = Buffer<X>(newCapacity(size1 + size2));
1608
-
1609
- var pointer1 = 0;
1610
- var pointer2 = 0;
1611
-
1612
- while (pointer1 < size1 and pointer2 < size2) {
1613
- let current1 = buffer1.get(pointer1);
1614
- let current2 = buffer2.get(pointer2);
1615
-
1616
- switch (compare(current1, current2)) {
1617
- case (#less) {
1618
- newBuffer.add(current1);
1619
- pointer1 += 1;
1620
- };
1621
- case _ {
1622
- newBuffer.add(current2);
1623
- pointer2 += 1;
1624
- };
1625
- };
1626
- };
1627
-
1628
- while (pointer1 < size1) {
1629
- newBuffer.add(buffer1.get(pointer1));
1630
- pointer1 += 1;
1631
- };
1632
-
1633
- while (pointer2 < size2) {
1634
- newBuffer.add(buffer2.get(pointer2));
1635
- pointer2 += 1;
1636
- };
1637
-
1638
- newBuffer;
1639
- };
1640
-
1641
- /// Eliminates all duplicate elements in `buffer` as defined by `compare`.
1642
- /// Elimination is stable with respect to the original ordering of the elements.
1643
- ///
1644
- /// Runtime: O(size * log(size))
1645
- ///
1646
- /// Space: O(size)
1647
- public func removeDuplicates<X>(buffer : Buffer<X>, compare : (X, X) -> Order) {
1648
- let size = buffer.size();
1649
- let indices = Prim.Array_tabulate<(Nat, X)>(size, func i = (i, buffer.get(i)));
1650
- // Sort based on element, while carrying original index information
1651
- // This groups together the duplicate elements
1652
- let sorted = Array.sort<(Nat, X)>(indices, func(pair1, pair2) = compare(pair1.1, pair2.1));
1653
- let uniques = Buffer<(Nat, X)>(size);
1654
-
1655
- // Iterate over elements
1656
- var i = 0;
1657
- while (i < size) {
1658
- var j = i;
1659
- // Iterate over duplicate elements, and find the smallest index among them (for stability)
1660
- var minIndex = sorted[j];
1661
- label duplicates while (j < (size - 1 : Nat)) {
1662
- let pair1 = sorted[j];
1663
- let pair2 = sorted[j + 1];
1664
- switch (compare(pair1.1, pair2.1)) {
1665
- case (#equal) {
1666
- if (pair2.0 < pair1.0) {
1667
- minIndex := pair2;
1668
- };
1669
- j += 1;
1670
- };
1671
- case _ {
1672
- break duplicates;
1673
- };
1674
- };
1675
- };
1676
-
1677
- uniques.add(minIndex);
1678
- i := j + 1;
1679
- };
1680
-
1681
- // resort based on original ordering and place back in buffer
1682
- uniques.sort(
1683
- func(pair1, pair2) {
1684
- if (pair1.0 < pair2.0) {
1685
- #less;
1686
- } else if (pair1.0 == pair2.0) {
1687
- #equal;
1688
- } else {
1689
- #greater;
1690
- };
1691
- },
1692
- );
1693
-
1694
- buffer.clear();
1695
- buffer.reserve(uniques.size());
1696
- for (element in uniques.vals()) {
1697
- buffer.add(element.1);
1698
- };
1699
- };
1700
-
1701
- /// Splits `buffer` into a pair of buffers where all elements in the left
1702
- /// buffer satisfy `predicate` and all elements in the right buffer do not.
1703
- ///
1704
- /// Runtime: O(size)
1705
- ///
1706
- /// Space: O(size)
1707
- ///
1708
- /// *Runtime and space assumes that `predicate` runs in O(1) time and space.
1709
- public func partition<X>(buffer : Buffer<X>, predicate : X -> Bool) : (Buffer<X>, Buffer<X>) {
1710
- let size = buffer.size();
1711
- let trueBuffer = Buffer<X>(size);
1712
- let falseBuffer = Buffer<X>(size);
1713
-
1714
- for (element in buffer.vals()) {
1715
- if (predicate element) {
1716
- trueBuffer.add(element);
1717
- } else {
1718
- falseBuffer.add(element);
1719
- };
1720
- };
1721
-
1722
- (trueBuffer, falseBuffer);
1723
- };
1724
-
1725
- /// Splits the buffer into two buffers at `index`, where the left buffer contains
1726
- /// all elements with indices less than `index`, and the right buffer contains all
1727
- /// elements with indices greater than or equal to `index`. Traps if `index` is out
1728
- /// of bounds.
1729
- ///
1730
- /// Runtime: O(size)
1731
- ///
1732
- /// Space: O(size)
1733
- ///
1734
- /// *Runtime and space assumes that `compare` runs in O(1) time and space.
1735
- public func split<X>(buffer : Buffer<X>, index : Nat) : (Buffer<X>, Buffer<X>) {
1736
- let size = buffer.size();
1737
-
1738
- if (index < 0 or index > size) {
1739
- Prim.trap "Index out of bounds in split";
1740
- };
1741
-
1742
- let buffer1 = Buffer<X>(newCapacity index);
1743
- let buffer2 = Buffer<X>(newCapacity(size - index));
1744
-
1745
- var i = 0;
1746
- while (i < index) {
1747
- buffer1.add(buffer.get(i));
1748
- i += 1;
1749
- };
1750
- while (i < size) {
1751
- buffer2.add(buffer.get(i));
1752
- i += 1;
1753
- };
1754
-
1755
- (buffer1, buffer2);
1756
- };
1757
-
1758
- /// Breaks up `buffer` into buffers of size `size`. The last chunk may
1759
- /// have less than `size` elements if the number of elements is not divisible
1760
- /// by the chunk size.
1761
- ///
1762
- /// Runtime: O(number of elements in buffer)
1763
- ///
1764
- /// Space: O(number of elements in buffer)
1765
- public func chunk<X>(buffer : Buffer<X>, size : Nat) : Buffer<Buffer<X>> {
1766
- if (size == 0) {
1767
- Prim.trap "Chunk size must be non-zero in chunk";
1768
- };
1769
-
1770
- // ceil(buffer.size() / size)
1771
- let newBuffer = Buffer<Buffer<X>>((buffer.size() + size - 1) / size);
1772
-
1773
- var newInnerBuffer = Buffer<X>(newCapacity size);
1774
- var innerSize = 0;
1775
- for (element in buffer.vals()) {
1776
- if (innerSize == size) {
1777
- newBuffer.add(newInnerBuffer);
1778
- newInnerBuffer := Buffer<X>(newCapacity size);
1779
- innerSize := 0;
1780
- };
1781
- newInnerBuffer.add(element);
1782
- innerSize += 1;
1783
- };
1784
- if (innerSize > 0) {
1785
- newBuffer.add(newInnerBuffer);
1786
- };
1787
-
1788
- newBuffer;
1789
- };
1790
-
1791
- /// Groups equal and adjacent elements in the list into sub lists.
1792
- ///
1793
- /// Runtime: O(size)
1794
- ///
1795
- /// Space: O(size)
1796
- ///
1797
- /// *Runtime and space assumes that `equal` runs in O(1) time and space.
1798
- public func groupBy<X>(buffer : Buffer<X>, equal : (X, X) -> Bool) : Buffer<Buffer<X>> {
1799
- let size = buffer.size();
1800
- let newBuffer = Buffer<Buffer<X>>(size);
1801
- if (size == 0) {
1802
- return newBuffer;
1803
- };
1804
-
1805
- var i = 0;
1806
- var baseElement = buffer.get(0);
1807
- var newInnerBuffer = Buffer<X>(size);
1808
- while (i < size) {
1809
- let element = buffer.get(i);
1810
-
1811
- if (equal(baseElement, element)) {
1812
- newInnerBuffer.add(element);
1813
- } else {
1814
- newBuffer.add(newInnerBuffer);
1815
- baseElement := element;
1816
- newInnerBuffer := Buffer<X>(size - i);
1817
- newInnerBuffer.add(element);
1818
- };
1819
- i += 1;
1820
- };
1821
- if (newInnerBuffer.size() > 0) {
1822
- newBuffer.add(newInnerBuffer);
1823
- };
1824
-
1825
- newBuffer;
1826
- };
1827
-
1828
- /// Flattens the buffer of buffers into a single buffer.
1829
- ///
1830
- /// Runtime: O(number of elements in buffer)
1831
- ///
1832
- /// Space: O(number of elements in buffer)
1833
- public func flatten<X>(buffer : Buffer<Buffer<X>>) : Buffer<X> {
1834
- let size = buffer.size();
1835
- if (size == 0) {
1836
- return Buffer<X>(0);
1837
- };
1838
-
1839
- let newBuffer = Buffer<X>(
1840
- if (buffer.get(0).size() != 0) {
1841
- newCapacity(buffer.get(0).size() * size);
1842
- } else {
1843
- newCapacity(size);
1844
- },
1845
- );
1846
-
1847
- for (innerBuffer in buffer.vals()) {
1848
- for (innerElement in innerBuffer.vals()) {
1849
- newBuffer.add(innerElement);
1850
- };
1851
- };
1852
-
1853
- newBuffer;
1854
- };
1855
-
1856
- /// Combines the two buffers into a single buffer of pairs, pairing together
1857
- /// elements with the same index. If one buffer is longer than the other, the
1858
- /// remaining elements from the longer buffer are not included.
1859
- ///
1860
- /// Runtime: O(min(size1, size2))
1861
- ///
1862
- /// Space: O(min(size1, size2))
1863
- public func zip<X, Y>(buffer1 : Buffer<X>, buffer2 : Buffer<Y>) : Buffer<(X, Y)> {
1864
- // compiler should pull lamda out as a static function since it is fully closed
1865
- zipWith<X, Y, (X, Y)>(buffer1, buffer2, func(x, y) = (x, y));
1866
- };
1867
-
1868
- /// Combines the two buffers into a single buffer, pairing together
1869
- /// elements with the same index and combining them using `zip`. If
1870
- /// one buffer is longer than the other, the remaining elements from
1871
- /// the longer buffer are not included.
1872
- ///
1873
- /// Runtime: O(min(size1, size2))
1874
- ///
1875
- /// Space: O(min(size1, size2))
1876
- ///
1877
- /// *Runtime and space assumes that `zip` runs in O(1) time and space.
1878
- public func zipWith<X, Y, Z>(buffer1 : Buffer<X>, buffer2 : Buffer<Y>, zip : (X, Y) -> Z) : Buffer<Z> {
1879
- let size1 = buffer1.size();
1880
- let size2 = buffer2.size();
1881
- let minSize = if (size1 < size2) { size1 } else { size2 };
1882
-
1883
- var i = 0;
1884
- let newBuffer = Buffer<Z>(newCapacity minSize);
1885
- while (i < minSize) {
1886
- newBuffer.add(zip(buffer1.get(i), buffer2.get(i)));
1887
- i += 1;
1888
- };
1889
- newBuffer;
1890
- };
1891
-
1892
- /// Creates a new buffer taking elements in order from `buffer` until predicate
1893
- /// returns false.
1894
- ///
1895
- /// Runtime: O(size)
1896
- ///
1897
- /// Space: O(size)
1898
- ///
1899
- /// *Runtime and space assumes that `predicate` runs in O(1) time and space.
1900
- public func takeWhile<X>(buffer : Buffer<X>, predicate : X -> Bool) : Buffer<X> {
1901
- let newBuffer = Buffer<X>(buffer.size());
1902
-
1903
- for (element in buffer.vals()) {
1904
- if (not predicate element) {
1905
- return newBuffer;
1906
- };
1907
- newBuffer.add(element);
1908
- };
1909
-
1910
- newBuffer;
1911
- };
1912
-
1913
- /// Creates a new buffer excluding elements in order from `buffer` until predicate
1914
- /// returns false.
1915
- ///
1916
- /// Runtime: O(size)
1917
- ///
1918
- /// Space: O(size)
1919
- ///
1920
- /// *Runtime and space assumes that `predicate` runs in O(1) time and space.
1921
- public func dropWhile<X>(buffer : Buffer<X>, predicate : X -> Bool) : Buffer<X> {
1922
- let size = buffer.size();
1923
- let newBuffer = Buffer<X>(size);
1924
-
1925
- var i = 0;
1926
- var take = false;
1927
- label iter for (element in buffer.vals()) {
1928
- if (not (take or predicate element)) {
1929
- take := true;
1930
- };
1931
- if (take) {
1932
- newBuffer.add(element);
1933
- };
1934
- };
1935
- newBuffer;
1936
- };
1937
- };