@grain/stdlib 0.5.12 → 0.6.0
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/CHANGELOG.md +200 -0
- package/LICENSE +1 -1
- package/README.md +25 -2
- package/array.gr +1512 -199
- package/array.md +2032 -94
- package/bigint.gr +239 -140
- package/bigint.md +450 -106
- package/buffer.gr +595 -102
- package/buffer.md +903 -145
- package/bytes.gr +401 -110
- package/bytes.md +551 -63
- package/char.gr +228 -49
- package/char.md +373 -7
- package/exception.gr +26 -12
- package/exception.md +29 -5
- package/float32.gr +130 -109
- package/float32.md +185 -57
- package/float64.gr +112 -99
- package/float64.md +185 -57
- package/hash.gr +47 -37
- package/hash.md +21 -3
- package/int16.gr +430 -0
- package/int16.md +618 -0
- package/int32.gr +200 -269
- package/int32.md +254 -289
- package/int64.gr +142 -225
- package/int64.md +254 -289
- package/int8.gr +511 -0
- package/int8.md +786 -0
- package/json.gr +2084 -0
- package/json.md +608 -0
- package/list.gr +120 -68
- package/list.md +125 -80
- package/map.gr +560 -57
- package/map.md +672 -56
- package/marshal.gr +239 -227
- package/marshal.md +36 -4
- package/number.gr +626 -676
- package/number.md +738 -153
- package/option.gr +33 -35
- package/option.md +58 -42
- package/package.json +2 -2
- package/path.gr +148 -187
- package/path.md +47 -96
- package/pervasives.gr +75 -416
- package/pervasives.md +85 -180
- package/priorityqueue.gr +433 -74
- package/priorityqueue.md +422 -54
- package/queue.gr +362 -80
- package/queue.md +433 -38
- package/random.gr +67 -75
- package/random.md +68 -40
- package/range.gr +135 -63
- package/range.md +198 -43
- package/rational.gr +284 -0
- package/rational.md +545 -0
- package/regex.gr +933 -1066
- package/regex.md +59 -60
- package/result.gr +23 -25
- package/result.md +54 -39
- package/runtime/atof/common.gr +78 -82
- package/runtime/atof/common.md +22 -10
- package/runtime/atof/decimal.gr +102 -127
- package/runtime/atof/decimal.md +28 -7
- package/runtime/atof/lemire.gr +56 -71
- package/runtime/atof/lemire.md +9 -1
- package/runtime/atof/parse.gr +83 -110
- package/runtime/atof/parse.md +12 -2
- package/runtime/atof/slow.gr +28 -35
- package/runtime/atof/slow.md +9 -1
- package/runtime/atof/table.gr +19 -18
- package/runtime/atof/table.md +10 -2
- package/runtime/atoi/parse.gr +153 -136
- package/runtime/atoi/parse.md +50 -1
- package/runtime/bigint.gr +410 -517
- package/runtime/bigint.md +71 -57
- package/runtime/compare.gr +176 -85
- package/runtime/compare.md +31 -1
- package/runtime/dataStructures.gr +144 -32
- package/runtime/dataStructures.md +267 -31
- package/runtime/debugPrint.gr +34 -15
- package/runtime/debugPrint.md +37 -5
- package/runtime/equal.gr +53 -52
- package/runtime/equal.md +30 -1
- package/runtime/exception.gr +38 -47
- package/runtime/exception.md +10 -8
- package/runtime/gc.gr +23 -152
- package/runtime/gc.md +13 -17
- package/runtime/malloc.gr +31 -31
- package/runtime/malloc.md +11 -3
- package/runtime/numberUtils.gr +191 -172
- package/runtime/numberUtils.md +17 -9
- package/runtime/numbers.gr +1695 -1021
- package/runtime/numbers.md +1098 -134
- package/runtime/string.gr +540 -242
- package/runtime/string.md +76 -6
- package/runtime/unsafe/constants.gr +30 -13
- package/runtime/unsafe/constants.md +80 -0
- package/runtime/unsafe/conv.gr +55 -28
- package/runtime/unsafe/conv.md +41 -9
- package/runtime/unsafe/memory.gr +10 -30
- package/runtime/unsafe/memory.md +15 -19
- package/runtime/unsafe/tags.gr +37 -21
- package/runtime/unsafe/tags.md +88 -8
- package/runtime/unsafe/wasmf32.gr +30 -36
- package/runtime/unsafe/wasmf32.md +64 -56
- package/runtime/unsafe/wasmf64.gr +30 -36
- package/runtime/unsafe/wasmf64.md +64 -56
- package/runtime/unsafe/wasmi32.gr +49 -66
- package/runtime/unsafe/wasmi32.md +102 -94
- package/runtime/unsafe/wasmi64.gr +52 -79
- package/runtime/unsafe/wasmi64.md +108 -100
- package/runtime/utils/printing.gr +13 -15
- package/runtime/utils/printing.md +11 -3
- package/runtime/wasi.gr +294 -295
- package/runtime/wasi.md +62 -42
- package/set.gr +574 -64
- package/set.md +634 -54
- package/stack.gr +181 -64
- package/stack.md +271 -42
- package/string.gr +453 -533
- package/string.md +241 -151
- package/uint16.gr +369 -0
- package/uint16.md +585 -0
- package/uint32.gr +470 -0
- package/uint32.md +737 -0
- package/uint64.gr +471 -0
- package/uint64.md +737 -0
- package/uint8.gr +369 -0
- package/uint8.md +585 -0
- package/uri.gr +1093 -0
- package/uri.md +477 -0
- package/{sys → wasi}/file.gr +914 -500
- package/{sys → wasi}/file.md +454 -50
- package/wasi/process.gr +292 -0
- package/{sys → wasi}/process.md +164 -6
- package/wasi/random.gr +77 -0
- package/wasi/random.md +80 -0
- package/{sys → wasi}/time.gr +15 -22
- package/{sys → wasi}/time.md +5 -5
- package/immutablearray.gr +0 -929
- package/immutablearray.md +0 -1038
- package/immutablemap.gr +0 -493
- package/immutablemap.md +0 -479
- package/immutablepriorityqueue.gr +0 -360
- package/immutablepriorityqueue.md +0 -291
- package/immutableset.gr +0 -498
- package/immutableset.md +0 -449
- package/runtime/debug.gr +0 -2
- package/runtime/debug.md +0 -6
- package/runtime/unsafe/errors.gr +0 -36
- package/runtime/unsafe/errors.md +0 -204
- package/sys/process.gr +0 -254
- package/sys/random.gr +0 -79
- package/sys/random.md +0 -66
package/list.gr
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Utilities for working with lists.
|
|
3
3
|
*
|
|
4
|
-
* @example
|
|
4
|
+
* @example from "list" include List
|
|
5
5
|
*
|
|
6
6
|
* @since v0.2.0
|
|
7
7
|
* @history v0.1.0: Originally named `lists`
|
|
8
8
|
* @history v0.2.0: Renamed to `list`
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @section Values: Functions for working with the List data type.
|
|
13
|
-
*/
|
|
10
|
+
module List
|
|
14
11
|
|
|
15
12
|
/**
|
|
16
13
|
* Creates a new list of the specified length where each element is
|
|
@@ -25,7 +22,7 @@
|
|
|
25
22
|
*
|
|
26
23
|
* @since v0.3.0
|
|
27
24
|
*/
|
|
28
|
-
|
|
25
|
+
provide let init = (length, fn) => {
|
|
29
26
|
// This method can be further improved by checking the length against a specific size
|
|
30
27
|
// and determining if it can be made tail-recursive, then use List.reverse on it.
|
|
31
28
|
// Which would be the same as OCaml does it in https://github.com/ocaml/ocaml/blob/03839754f46319aa36d9dad56940a6f3c3bcb48a/stdlib/list.ml#L79
|
|
@@ -48,7 +45,7 @@ export let init = (length, fn) => {
|
|
|
48
45
|
* @since v0.1.0
|
|
49
46
|
* @history v0.2.0: Made the function tail-recursive
|
|
50
47
|
*/
|
|
51
|
-
|
|
48
|
+
provide let length = list => {
|
|
52
49
|
let rec iter = (len, list) => {
|
|
53
50
|
match (list) {
|
|
54
51
|
[] => len,
|
|
@@ -58,6 +55,21 @@ export let length = list => {
|
|
|
58
55
|
iter(0, list)
|
|
59
56
|
}
|
|
60
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Determines if the list contains no elements.
|
|
60
|
+
*
|
|
61
|
+
* @param list: The list to inspect
|
|
62
|
+
* @returns `true` if the list is empty and `false` otherwise
|
|
63
|
+
*
|
|
64
|
+
* @since v0.6.0
|
|
65
|
+
*/
|
|
66
|
+
provide let isEmpty = list => {
|
|
67
|
+
match (list) {
|
|
68
|
+
[] => true,
|
|
69
|
+
_ => false,
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
61
73
|
/**
|
|
62
74
|
* Creates a new list with all elements in reverse order.
|
|
63
75
|
*
|
|
@@ -66,7 +78,7 @@ export let length = list => {
|
|
|
66
78
|
*
|
|
67
79
|
* @since v0.1.0
|
|
68
80
|
*/
|
|
69
|
-
|
|
81
|
+
provide let reverse = list => {
|
|
70
82
|
let rec iter = (list, acc) => {
|
|
71
83
|
match (list) {
|
|
72
84
|
[] => acc,
|
|
@@ -86,7 +98,7 @@ export let reverse = list => {
|
|
|
86
98
|
*
|
|
87
99
|
* @since v0.1.0
|
|
88
100
|
*/
|
|
89
|
-
|
|
101
|
+
provide let rec append = (list1, list2) => {
|
|
90
102
|
match (list1) {
|
|
91
103
|
[] => list2,
|
|
92
104
|
[first, ...rest] => [first, ...append(rest, list2)],
|
|
@@ -103,7 +115,7 @@ export let rec append = (list1, list2) => {
|
|
|
103
115
|
*
|
|
104
116
|
* @since v0.1.0
|
|
105
117
|
*/
|
|
106
|
-
|
|
118
|
+
provide let rec contains = (search, list) => {
|
|
107
119
|
match (list) {
|
|
108
120
|
[] => false,
|
|
109
121
|
[first, ...rest] => first == search || contains(search, rest),
|
|
@@ -130,7 +142,7 @@ export let rec contains = (search, list) => {
|
|
|
130
142
|
* @history v0.1.0: Originally named `foldLeft`
|
|
131
143
|
* @history v0.2.0: Renamed to `reduce`
|
|
132
144
|
*/
|
|
133
|
-
|
|
145
|
+
provide let rec reduce = (fn, initial, list) => {
|
|
134
146
|
match (list) {
|
|
135
147
|
[] => initial,
|
|
136
148
|
[first, ...rest] => reduce(fn, fn(initial, first), rest),
|
|
@@ -157,7 +169,7 @@ export let rec reduce = (fn, initial, list) => {
|
|
|
157
169
|
* @history v0.1.0: Originally named `foldRight`
|
|
158
170
|
* @history v0.2.0: Renamed to `reduceRight`
|
|
159
171
|
*/
|
|
160
|
-
|
|
172
|
+
provide let rec reduceRight = (fn, initial, list) => {
|
|
161
173
|
match (list) {
|
|
162
174
|
[] => initial,
|
|
163
175
|
[first, ...rest] => fn(first, reduceRight(fn, initial, rest)),
|
|
@@ -174,7 +186,7 @@ export let rec reduceRight = (fn, initial, list) => {
|
|
|
174
186
|
*
|
|
175
187
|
* @since v0.1.0
|
|
176
188
|
*/
|
|
177
|
-
|
|
189
|
+
provide let rec map = (fn, list) => {
|
|
178
190
|
match (list) {
|
|
179
191
|
[] => [],
|
|
180
192
|
[first, ...rest] => [fn(first), ...map(fn, rest)],
|
|
@@ -191,7 +203,7 @@ export let rec map = (fn, list) => {
|
|
|
191
203
|
*
|
|
192
204
|
* @since v0.1.0
|
|
193
205
|
*/
|
|
194
|
-
|
|
206
|
+
provide let mapi = (fn, list) => {
|
|
195
207
|
let rec iter = (fn, list, index) => {
|
|
196
208
|
match (list) {
|
|
197
209
|
[] => [],
|
|
@@ -213,7 +225,7 @@ export let mapi = (fn, list) => {
|
|
|
213
225
|
*
|
|
214
226
|
* @since v0.2.0
|
|
215
227
|
*/
|
|
216
|
-
|
|
228
|
+
provide let rec flatMap = (fn, list) => {
|
|
217
229
|
match (list) {
|
|
218
230
|
[] => [],
|
|
219
231
|
[first, ...rest] => append(fn(first), flatMap(fn, rest)),
|
|
@@ -230,7 +242,7 @@ export let rec flatMap = (fn, list) => {
|
|
|
230
242
|
*
|
|
231
243
|
* @since v0.1.0
|
|
232
244
|
*/
|
|
233
|
-
|
|
245
|
+
provide let rec every = (fn, list) => {
|
|
234
246
|
match (list) {
|
|
235
247
|
[] => true,
|
|
236
248
|
// The short-circuiting of `&&` makes this tail-recursive
|
|
@@ -248,7 +260,7 @@ export let rec every = (fn, list) => {
|
|
|
248
260
|
*
|
|
249
261
|
* @since v0.1.0
|
|
250
262
|
*/
|
|
251
|
-
|
|
263
|
+
provide let rec some = (fn, list) => {
|
|
252
264
|
match (list) {
|
|
253
265
|
[] => false,
|
|
254
266
|
// The short-circuiting of `||` makes this tail-recursive
|
|
@@ -264,7 +276,7 @@ export let rec some = (fn, list) => {
|
|
|
264
276
|
*
|
|
265
277
|
* @since v0.1.0
|
|
266
278
|
*/
|
|
267
|
-
|
|
279
|
+
provide let rec forEach = (fn, list) => {
|
|
268
280
|
match (list) {
|
|
269
281
|
[] => void,
|
|
270
282
|
[first, ...rest] => {
|
|
@@ -283,7 +295,7 @@ export let rec forEach = (fn, list) => {
|
|
|
283
295
|
*
|
|
284
296
|
* @since v0.1.0
|
|
285
297
|
*/
|
|
286
|
-
|
|
298
|
+
provide let forEachi = (fn, list) => {
|
|
287
299
|
let rec iter = (fn, list, index) => {
|
|
288
300
|
match (list) {
|
|
289
301
|
[] => void,
|
|
@@ -307,7 +319,7 @@ export let forEachi = (fn, list) => {
|
|
|
307
319
|
*
|
|
308
320
|
* @since v0.1.0
|
|
309
321
|
*/
|
|
310
|
-
|
|
322
|
+
provide let rec filter = (fn, list) => {
|
|
311
323
|
match (list) {
|
|
312
324
|
[] => [],
|
|
313
325
|
[first, ...rest] =>
|
|
@@ -326,13 +338,15 @@ export let rec filter = (fn, list) => {
|
|
|
326
338
|
*
|
|
327
339
|
* @since v0.3.0
|
|
328
340
|
*/
|
|
329
|
-
|
|
341
|
+
provide let filteri = (fn, list) => {
|
|
330
342
|
let rec iter = (fn, list, index) => {
|
|
331
343
|
match (list) {
|
|
332
344
|
[] => [],
|
|
333
345
|
[first, ...rest] =>
|
|
334
|
-
if (fn(first, index))
|
|
335
|
-
|
|
346
|
+
if (fn(first, index))
|
|
347
|
+
[first, ...iter(fn, rest, index + 1)]
|
|
348
|
+
else
|
|
349
|
+
iter(fn, rest, index + 1),
|
|
336
350
|
}
|
|
337
351
|
}
|
|
338
352
|
iter(fn, list, 0)
|
|
@@ -349,7 +363,7 @@ export let filteri = (fn, list) => {
|
|
|
349
363
|
*
|
|
350
364
|
* @since v0.1.0
|
|
351
365
|
*/
|
|
352
|
-
|
|
366
|
+
provide let rec reject = (fn, list) => {
|
|
353
367
|
match (list) {
|
|
354
368
|
[] => [],
|
|
355
369
|
[first, ...rest] =>
|
|
@@ -369,7 +383,7 @@ export let rec reject = (fn, list) => {
|
|
|
369
383
|
* @history v0.2.0: Renamed to `head`
|
|
370
384
|
* @history v0.3.0: Return type converted to `Option` type
|
|
371
385
|
*/
|
|
372
|
-
|
|
386
|
+
provide let head = list => {
|
|
373
387
|
match (list) {
|
|
374
388
|
[] => None,
|
|
375
389
|
[first, ..._] => Some(first),
|
|
@@ -388,7 +402,7 @@ export let head = list => {
|
|
|
388
402
|
* @history v0.2.0: Renamed to `tail`
|
|
389
403
|
* @history v0.3.0: Return type converted to `Option` type
|
|
390
404
|
*/
|
|
391
|
-
|
|
405
|
+
provide let tail = list => {
|
|
392
406
|
match (list) {
|
|
393
407
|
[] => None,
|
|
394
408
|
[_, ...rest] => Some(rest),
|
|
@@ -407,7 +421,7 @@ export let tail = list => {
|
|
|
407
421
|
* @history v0.1.0: Originally failed for index out-of-bounds or list empty
|
|
408
422
|
* @history v0.3.0: Return type converted to `Option` type
|
|
409
423
|
*/
|
|
410
|
-
|
|
424
|
+
provide let rec nth = (index, list) => {
|
|
411
425
|
if (index < 0) {
|
|
412
426
|
None
|
|
413
427
|
} else {
|
|
@@ -428,7 +442,7 @@ export let rec nth = (index, list) => {
|
|
|
428
442
|
*
|
|
429
443
|
* @since v0.1.0
|
|
430
444
|
*/
|
|
431
|
-
|
|
445
|
+
provide let rec flatten = list => {
|
|
432
446
|
match (list) {
|
|
433
447
|
[] => [],
|
|
434
448
|
[first, ...rest] => append(first, flatten(rest)),
|
|
@@ -438,8 +452,8 @@ export let rec flatten = list => {
|
|
|
438
452
|
/**
|
|
439
453
|
* Inserts a new value into a list at the specified index.
|
|
440
454
|
*
|
|
441
|
-
* @param value: The value to insert
|
|
442
455
|
* @param index: The index to update
|
|
456
|
+
* @param value: The value to insert
|
|
443
457
|
* @param list: The list to update
|
|
444
458
|
* @returns The new list
|
|
445
459
|
*
|
|
@@ -447,16 +461,19 @@ export let rec flatten = list => {
|
|
|
447
461
|
* @throws Failure(String): When `index` is more than 0 and greater than the list size
|
|
448
462
|
*
|
|
449
463
|
* @since v0.1.0
|
|
464
|
+
* @history v0.6.0: Swapped order of `index` and `value` parameters
|
|
450
465
|
*/
|
|
451
|
-
|
|
466
|
+
provide let rec insert = (index, value, list) => {
|
|
452
467
|
if (index < 0) {
|
|
453
468
|
fail "insert index cannot be a negative number"
|
|
454
469
|
} else {
|
|
455
470
|
match (list) {
|
|
456
471
|
[] => if (index == 0) [value] else fail "insert index is out-of-bounds",
|
|
457
472
|
[first, ...rest] =>
|
|
458
|
-
if (index == 0)
|
|
459
|
-
|
|
473
|
+
if (index == 0)
|
|
474
|
+
[value, ...list]
|
|
475
|
+
else
|
|
476
|
+
[first, ...insert(index - 1, value, rest)],
|
|
460
477
|
}
|
|
461
478
|
}
|
|
462
479
|
}
|
|
@@ -471,7 +488,7 @@ export let rec insert = (value, index, list) => {
|
|
|
471
488
|
* @since v0.1.0
|
|
472
489
|
* @history v0.2.0: Made the function tail-recursive
|
|
473
490
|
*/
|
|
474
|
-
|
|
491
|
+
provide let count = (fn, list) => {
|
|
475
492
|
let rec iter = (n, list) => {
|
|
476
493
|
match (list) {
|
|
477
494
|
[] => n,
|
|
@@ -493,7 +510,7 @@ export let count = (fn, list) => {
|
|
|
493
510
|
*
|
|
494
511
|
* @since v0.1.0
|
|
495
512
|
*/
|
|
496
|
-
|
|
513
|
+
provide let part = (count, list) => {
|
|
497
514
|
if (count < 0) {
|
|
498
515
|
fail "part count cannot be a negative number"
|
|
499
516
|
} else {
|
|
@@ -502,8 +519,10 @@ export let part = (count, list) => {
|
|
|
502
519
|
[] =>
|
|
503
520
|
if (count > 0) fail "part count is out-of-bounds" else (list1, list2),
|
|
504
521
|
[first, ...rest] =>
|
|
505
|
-
if (count > 0)
|
|
506
|
-
|
|
522
|
+
if (count > 0)
|
|
523
|
+
iter([first, ...list1], rest, count - 1)
|
|
524
|
+
else
|
|
525
|
+
(list1, list2),
|
|
507
526
|
}
|
|
508
527
|
}
|
|
509
528
|
let (pt1, pt2) = iter([], list, count)
|
|
@@ -512,24 +531,50 @@ export let part = (count, list) => {
|
|
|
512
531
|
}
|
|
513
532
|
|
|
514
533
|
/**
|
|
515
|
-
* Rotates list elements by the specified amount to the left
|
|
534
|
+
* Rotates list elements by the specified amount to the left, such that `n`th
|
|
535
|
+
* element is the first in the new list.
|
|
516
536
|
*
|
|
517
537
|
* If value is negative, list elements will be rotated by the
|
|
518
538
|
* specified amount to the right. See examples.
|
|
519
539
|
*
|
|
520
|
-
* @param
|
|
540
|
+
* @param n: The number of elements to rotate by
|
|
521
541
|
* @param list: The list to be rotated
|
|
522
542
|
*
|
|
523
543
|
* @example List.rotate(2, [1, 2, 3, 4, 5]) // [3, 4, 5, 1, 2]
|
|
524
544
|
* @example List.rotate(-1, [1, 2, 3, 4, 5]) // [5, 1, 2, 3, 4]
|
|
525
|
-
*
|
|
526
|
-
* @throws Failure(String): When the list doesn't contain at least the required amount of elements
|
|
545
|
+
* @example List.rotate(-7, [1, 2, 3, 4, 5]) // [4, 5, 1, 2, 3]
|
|
527
546
|
*
|
|
528
547
|
* @since v0.1.0
|
|
548
|
+
*
|
|
549
|
+
* @history v0.6.0: No longer throws if `count` outside list length bounds
|
|
529
550
|
*/
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
551
|
+
provide let rotate = (n, list) => {
|
|
552
|
+
// Optimization: only compute the list length (O(n)) if n is negative
|
|
553
|
+
// or if the entire list is exhausted when partitioning. This should improve
|
|
554
|
+
// performance if the list is very long but n is small
|
|
555
|
+
let getSplitI = () => {
|
|
556
|
+
let len = length(list)
|
|
557
|
+
if (len == 0) 0 else n % len
|
|
558
|
+
}
|
|
559
|
+
let (beginning, end) = if (n >= 0) {
|
|
560
|
+
let rec iter = (list1, list2, n) => {
|
|
561
|
+
match (list2) {
|
|
562
|
+
[] => if (n > 0) None else Some((list1, list2)),
|
|
563
|
+
[first, ...rest] =>
|
|
564
|
+
if (n > 0)
|
|
565
|
+
iter([first, ...list1], rest, n - 1)
|
|
566
|
+
else
|
|
567
|
+
Some((list1, list2)),
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
let res = iter([], list, n)
|
|
571
|
+
match (res) {
|
|
572
|
+
None => part(getSplitI(), list),
|
|
573
|
+
Some((pt1, pt2)) => (reverse(pt1), pt2),
|
|
574
|
+
}
|
|
575
|
+
} else {
|
|
576
|
+
part(getSplitI(), list)
|
|
577
|
+
}
|
|
533
578
|
append(end, beginning)
|
|
534
579
|
}
|
|
535
580
|
|
|
@@ -544,13 +589,15 @@ export let rotate = (count, list) => {
|
|
|
544
589
|
* @history v0.1.0: Originally named `uniq`
|
|
545
590
|
* @history v0.2.0: Renamed to `unique`
|
|
546
591
|
*/
|
|
547
|
-
|
|
592
|
+
provide let unique = list => {
|
|
548
593
|
let rec iter = (list, acc) => {
|
|
549
594
|
match (list) {
|
|
550
595
|
[] => reverse(acc),
|
|
551
596
|
[first, ...rest] =>
|
|
552
|
-
if (contains(first, acc))
|
|
553
|
-
|
|
597
|
+
if (contains(first, acc))
|
|
598
|
+
iter(rest, acc)
|
|
599
|
+
else
|
|
600
|
+
iter(rest, [first, ...acc]),
|
|
554
601
|
}
|
|
555
602
|
}
|
|
556
603
|
iter(list, [])
|
|
@@ -573,7 +620,7 @@ export let unique = list => {
|
|
|
573
620
|
*
|
|
574
621
|
* @since v0.5.3
|
|
575
622
|
*/
|
|
576
|
-
|
|
623
|
+
provide let zip = (list1, list2) => {
|
|
577
624
|
let rec zipInner = (list1, list2, acc) => {
|
|
578
625
|
match ((list1, list2)) {
|
|
579
626
|
([first1, ...rest1], [first2, ...rest2]) =>
|
|
@@ -604,7 +651,7 @@ export let zip = (list1, list2) => {
|
|
|
604
651
|
*
|
|
605
652
|
* @since v0.5.3
|
|
606
653
|
*/
|
|
607
|
-
|
|
654
|
+
provide let zipWith = (fn, list1, list2) => {
|
|
608
655
|
let rec zipWithInner = (list1, list2, acc) => {
|
|
609
656
|
match ((list1, list2)) {
|
|
610
657
|
([first1, ...rest1], [first2, ...rest2]) =>
|
|
@@ -623,10 +670,14 @@ export let zipWith = (fn, list1, list2) => {
|
|
|
623
670
|
*
|
|
624
671
|
* @since v0.5.3
|
|
625
672
|
*/
|
|
626
|
-
|
|
627
|
-
reduceRight(
|
|
628
|
-
(
|
|
629
|
-
|
|
673
|
+
provide let unzip = list => {
|
|
674
|
+
reduceRight(
|
|
675
|
+
((first, second), (firstUnzipped, secondUnzipped)) => {
|
|
676
|
+
([first, ...firstUnzipped], [second, ...secondUnzipped])
|
|
677
|
+
},
|
|
678
|
+
([], []),
|
|
679
|
+
list
|
|
680
|
+
)
|
|
630
681
|
}
|
|
631
682
|
|
|
632
683
|
/**
|
|
@@ -641,13 +692,13 @@ export let unzip = list => {
|
|
|
641
692
|
*
|
|
642
693
|
* @since v0.2.0
|
|
643
694
|
*/
|
|
644
|
-
|
|
695
|
+
provide let rec drop = (count, list) => {
|
|
645
696
|
if (count < 0) {
|
|
646
697
|
fail "number of items to drop cannot be a negative number"
|
|
647
698
|
} else {
|
|
648
699
|
match ((count, list)) {
|
|
649
700
|
(_, []) => [],
|
|
650
|
-
(
|
|
701
|
+
(0, _) => list,
|
|
651
702
|
(n, [first, ...rest]) => drop(n - 1, rest),
|
|
652
703
|
}
|
|
653
704
|
}
|
|
@@ -664,7 +715,7 @@ export let rec drop = (count, list) => {
|
|
|
664
715
|
*
|
|
665
716
|
* @since v0.2.0
|
|
666
717
|
*/
|
|
667
|
-
|
|
718
|
+
provide let rec dropWhile = (fn, list) => {
|
|
668
719
|
match (list) {
|
|
669
720
|
[] => list,
|
|
670
721
|
[first, ...rest] => if (fn(first)) dropWhile(fn, rest) else list,
|
|
@@ -683,13 +734,13 @@ export let rec dropWhile = (fn, list) => {
|
|
|
683
734
|
*
|
|
684
735
|
* @since v0.2.0
|
|
685
736
|
*/
|
|
686
|
-
|
|
737
|
+
provide let rec take = (count, list) => {
|
|
687
738
|
if (count < 0) {
|
|
688
739
|
fail "number of items to take cannot be a negative number"
|
|
689
740
|
} else {
|
|
690
741
|
match ((count, list)) {
|
|
691
742
|
(_, []) => list,
|
|
692
|
-
(
|
|
743
|
+
(0, _) => [],
|
|
693
744
|
(n, [first, ...rest]) => [first, ...take(n - 1, rest)],
|
|
694
745
|
}
|
|
695
746
|
}
|
|
@@ -706,7 +757,7 @@ export let rec take = (count, list) => {
|
|
|
706
757
|
*
|
|
707
758
|
* @since v0.2.0
|
|
708
759
|
*/
|
|
709
|
-
|
|
760
|
+
provide let rec takeWhile = (fn, list) => {
|
|
710
761
|
match (list) {
|
|
711
762
|
[] => [],
|
|
712
763
|
[first, ...rest] => if (fn(first)) [first, ...takeWhile(fn, rest)] else [],
|
|
@@ -724,7 +775,7 @@ export let rec takeWhile = (fn, list) => {
|
|
|
724
775
|
* @history v0.2.0: Originally failed if the list was empty
|
|
725
776
|
* @history v0.3.0: Return type converted to `Option` type
|
|
726
777
|
*/
|
|
727
|
-
|
|
778
|
+
provide let rec find = (fn, list) => {
|
|
728
779
|
match (list) {
|
|
729
780
|
[] => None,
|
|
730
781
|
[first, ...rest] => if (fn(first)) Some(first) else find(fn, rest),
|
|
@@ -742,7 +793,7 @@ export let rec find = (fn, list) => {
|
|
|
742
793
|
* @history v0.2.0: Originally failed if the list was empty
|
|
743
794
|
* @history v0.3.0: Return type converted to `Option` type
|
|
744
795
|
*/
|
|
745
|
-
|
|
796
|
+
provide let findIndex = (fn, list) => {
|
|
746
797
|
let rec findItemIndex = (l, index) => {
|
|
747
798
|
match (l) {
|
|
748
799
|
[] => None,
|
|
@@ -763,7 +814,7 @@ export let findIndex = (fn, list) => {
|
|
|
763
814
|
*
|
|
764
815
|
* @since v0.2.0
|
|
765
816
|
*/
|
|
766
|
-
|
|
817
|
+
provide let product = (list1, list2) => {
|
|
767
818
|
let mut list = []
|
|
768
819
|
forEach(aItem => {
|
|
769
820
|
forEach(bItem => {
|
|
@@ -787,7 +838,7 @@ export let product = (list1, list2) => {
|
|
|
787
838
|
*
|
|
788
839
|
* @since v0.2.0
|
|
789
840
|
*/
|
|
790
|
-
|
|
841
|
+
provide let sub = (start, length, list) => {
|
|
791
842
|
take(length, drop(start, list))
|
|
792
843
|
}
|
|
793
844
|
|
|
@@ -801,7 +852,7 @@ export let sub = (start, length, list) => {
|
|
|
801
852
|
*
|
|
802
853
|
* @since v0.4.0
|
|
803
854
|
*/
|
|
804
|
-
|
|
855
|
+
provide let join = (separator: String, list: List<String>) => {
|
|
805
856
|
let rec iter = (sep, acc, rem) => {
|
|
806
857
|
match (rem) {
|
|
807
858
|
[] => acc,
|
|
@@ -831,7 +882,7 @@ export let join = (separator: String, list: List<String>) => {
|
|
|
831
882
|
*
|
|
832
883
|
* @since v0.4.5
|
|
833
884
|
*/
|
|
834
|
-
|
|
885
|
+
provide let rec revAppend = (list1, list2) => {
|
|
835
886
|
match (list1) {
|
|
836
887
|
[hd, ...tl] => revAppend(tl, [hd, ...list2]),
|
|
837
888
|
[] => list2,
|
|
@@ -842,13 +893,14 @@ export let rec revAppend = (list1, list2) => {
|
|
|
842
893
|
* Sorts the given list based on a given comparator function. The resulting list is sorted in increasing order.
|
|
843
894
|
*
|
|
844
895
|
* Ordering is calculated using a comparator function which takes two list elements and must return 0 if both are equal, a positive number if the first is greater, and a negative number if the first is smaller.
|
|
845
|
-
* @param
|
|
896
|
+
* @param compare: The comparator function used to indicate sort order
|
|
846
897
|
* @param list: The list to be sorted
|
|
847
898
|
* @returns The sorted list
|
|
848
899
|
*
|
|
849
900
|
* @since v0.4.5
|
|
901
|
+
* @history v0.6.0: Made `compare` a default argument
|
|
850
902
|
*/
|
|
851
|
-
|
|
903
|
+
provide let sort = (compare=compare, list) => {
|
|
852
904
|
let rec merge = (left, right, list) => {
|
|
853
905
|
match ((left, right)) {
|
|
854
906
|
(_, []) => {
|
|
@@ -858,7 +910,7 @@ export let sort = (comp, list) => {
|
|
|
858
910
|
revAppend(list, right)
|
|
859
911
|
},
|
|
860
912
|
([lhd, ...ltl], [rhd, ...rtl]) => {
|
|
861
|
-
if (
|
|
913
|
+
if (compare(lhd, rhd) < 0) {
|
|
862
914
|
merge(ltl, right, append([lhd], list))
|
|
863
915
|
} else {
|
|
864
916
|
merge(left, rtl, append([rhd], list))
|