@grain/stdlib 0.4.2 → 0.4.6
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 +52 -0
- package/LICENSE +1 -1
- package/array.gr +200 -89
- package/array.md +81 -5
- package/buffer.gr +93 -36
- package/bytes.gr +10 -10
- package/char.gr +112 -56
- package/char.md +200 -0
- package/float32.gr +120 -4
- package/float32.md +315 -0
- package/float64.gr +120 -4
- package/float64.md +315 -0
- package/hash.gr +42 -15
- package/hash.md +44 -0
- package/int32.gr +370 -75
- package/int32.md +833 -0
- package/int64.gr +370 -75
- package/int64.md +833 -0
- package/list.gr +121 -50
- package/map.gr +106 -110
- package/number.gr +37 -1
- package/number.md +66 -0
- package/option.gr +260 -53
- package/option.md +579 -0
- package/package.json +1 -1
- package/pervasives.gr +32 -20
- package/queue.gr +102 -30
- package/queue.md +191 -0
- package/range.gr +26 -26
- package/range.md +1 -1
- package/regex.md +9 -9
- package/result.gr +216 -70
- package/result.md +446 -0
- package/runtime/dataStructures.gr +28 -29
- package/runtime/debug.gr +0 -1
- package/runtime/equal.gr +37 -16
- package/runtime/exception.gr +28 -15
- package/runtime/gc.gr +33 -20
- package/runtime/malloc.gr +19 -11
- package/runtime/numberUtils.gr +208 -103
- package/runtime/numbers.gr +217 -118
- package/runtime/string.gr +98 -39
- package/runtime/stringUtils.gr +176 -0
- package/runtime/unsafe/conv.gr +10 -10
- package/runtime/unsafe/memory.gr +14 -3
- package/runtime/unsafe/printWasm.gr +4 -4
- package/runtime/unsafe/tags.gr +2 -2
- package/runtime/unsafe/wasmf32.gr +9 -2
- package/runtime/unsafe/wasmf64.gr +9 -2
- package/runtime/unsafe/wasmi32.gr +65 -47
- package/runtime/unsafe/wasmi64.gr +78 -50
- package/runtime/wasi.gr +199 -45
- package/set.gr +281 -119
- package/set.md +502 -0
- package/stack.gr +26 -26
- package/string.gr +657 -341
- package/string.md +815 -0
- package/sys/file.gr +356 -177
- package/sys/process.gr +10 -6
- package/sys/random.gr +3 -6
- package/sys/time.gr +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
### [0.4.6](https://www.github.com/grain-lang/grain/compare/stdlib-v0.4.5...stdlib-v0.4.6) (2022-01-17)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **grainfmt:** Indent function application args when adding parens ([#1095](https://www.github.com/grain-lang/grain/issues/1095)) ([64af7d3](https://www.github.com/grain-lang/grain/commit/64af7d387dca2fddb9b3d190ccdf5790ec3d8e65))
|
|
9
|
+
|
|
10
|
+
### [0.4.5](https://www.github.com/grain-lang/grain/compare/stdlib-v0.4.4...stdlib-v0.4.5) (2021-12-31)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **stdlib:** Add sign function to Number module ([#1079](https://www.github.com/grain-lang/grain/issues/1079)) ([b6483d5](https://www.github.com/grain-lang/grain/commit/b6483d5046cd1b6b89a717a925594d3b20b05837))
|
|
16
|
+
|
|
17
|
+
### [0.4.4](https://www.github.com/grain-lang/grain/compare/stdlib-v0.4.3...stdlib-v0.4.4) (2021-12-11)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **stdlib:** Add reverse function to String module ([#1027](https://www.github.com/grain-lang/grain/issues/1027)) ([df761db](https://www.github.com/grain-lang/grain/commit/df761db55b3e14e31190090ae008ce5047135c09))
|
|
23
|
+
* **stdlib:** Add rotate function in Array module ([#838](https://www.github.com/grain-lang/grain/issues/838)) ([98fc577](https://www.github.com/grain-lang/grain/commit/98fc577ee754317cd2421bfaa8e3c1e049488949))
|
|
24
|
+
* **stdlib:** Add sort function to Array module ([#1012](https://www.github.com/grain-lang/grain/issues/1012)) ([9091930](https://www.github.com/grain-lang/grain/commit/9091930344224925bb7b2e1ef6f879c79a5c2f62))
|
|
25
|
+
* **stdlib:** Implement List.sort via mergesort ([#1014](https://www.github.com/grain-lang/grain/issues/1014)) ([a076e20](https://www.github.com/grain-lang/grain/commit/a076e200013114ccf16c2e6cbe814af1ec09c1ce))
|
|
26
|
+
* **stdlib:** Number.parseInt ([#1051](https://www.github.com/grain-lang/grain/issues/1051)) ([abafb58](https://www.github.com/grain-lang/grain/commit/abafb587e54219a32ed77ba09863bb2d6a80bac8))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Bug Fixes
|
|
30
|
+
|
|
31
|
+
* **graindoc:** Ensure value_description is resolved to outcome before printing ([#1070](https://www.github.com/grain-lang/grain/issues/1070)) ([5eb05cc](https://www.github.com/grain-lang/grain/commit/5eb05cc2dedc3b933e194be86dd5d3c3656d6490))
|
|
32
|
+
* **stdlib:** Add bounds checking to Buffer addStringSlice & addBytesSlice ([#1065](https://www.github.com/grain-lang/grain/issues/1065)) ([06fe512](https://www.github.com/grain-lang/grain/commit/06fe512e863aeeb855ccf3e3b83bcd3bc8854723))
|
|
33
|
+
* **stdlib:** Fix String.encode GC ([#1067](https://www.github.com/grain-lang/grain/issues/1067)) ([0ab38c9](https://www.github.com/grain-lang/grain/commit/0ab38c9f4aa0ee84688ba5c6bec1521b380d38b1))
|
|
34
|
+
* **stdlib:** Removed memory leak in Hash module ([#1045](https://www.github.com/grain-lang/grain/issues/1045)) ([01a81c6](https://www.github.com/grain-lang/grain/commit/01a81c6a2573cca94b2d57d0fc70693d39f810a1))
|
|
35
|
+
* **stdlib:** Removed memory leaks in Buffer module ([#1047](https://www.github.com/grain-lang/grain/issues/1047)) ([d33017b](https://www.github.com/grain-lang/grain/commit/d33017b37e988d3facbca2e30e3de4fb8c7b5b8a))
|
|
36
|
+
* **stdlib:** Support arrays of any type in Array rotate ([#1048](https://www.github.com/grain-lang/grain/issues/1048)) ([3ceb1cf](https://www.github.com/grain-lang/grain/commit/3ceb1cf04c1604f49077e8733dcccb6cdaaf9f3a))
|
|
37
|
+
* **stdlib:** Support empty arrays in Array rotate ([3ceb1cf](https://www.github.com/grain-lang/grain/commit/3ceb1cf04c1604f49077e8733dcccb6cdaaf9f3a))
|
|
38
|
+
|
|
39
|
+
### [0.4.3](https://www.github.com/grain-lang/grain/compare/stdlib-v0.4.2...stdlib-v0.4.3) (2021-10-27)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Features
|
|
43
|
+
|
|
44
|
+
* **stdlib:** Add cycle function to Array module ([#993](https://www.github.com/grain-lang/grain/issues/993)) ([c595622](https://www.github.com/grain-lang/grain/commit/c595622b28366655dfd5447270e8f9fc3f988a67))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### Bug Fixes
|
|
48
|
+
|
|
49
|
+
* **compiler:** Ensure TExpApp is always expansive in Grain ([ef0a69f](https://www.github.com/grain-lang/grain/commit/ef0a69fb4418d318b3227e5db7e743a026762274))
|
|
50
|
+
* **compiler:** Handle let-mut value restriction, such that mutable lets are always expansive ([ef0a69f](https://www.github.com/grain-lang/grain/commit/ef0a69fb4418d318b3227e5db7e743a026762274))
|
|
51
|
+
* **compiler:** Properly handle value restriction on function application & mutable vars ([#988](https://www.github.com/grain-lang/grain/issues/988)) ([ef0a69f](https://www.github.com/grain-lang/grain/commit/ef0a69fb4418d318b3227e5db7e743a026762274))
|
|
52
|
+
* **runtime:** Add types to boxed GC functions to avoid weak type errors ([ef0a69f](https://www.github.com/grain-lang/grain/commit/ef0a69fb4418d318b3227e5db7e743a026762274))
|
|
53
|
+
* **stdlib:** Fixed memory leak in String.explode ([#1001](https://www.github.com/grain-lang/grain/issues/1001)) ([c479a05](https://www.github.com/grain-lang/grain/commit/c479a05f48abcc4c9e98d5cf0ba698230d41031b))
|
|
54
|
+
|
|
3
55
|
### [0.4.2](https://www.github.com/grain-lang/grain/compare/stdlib-v0.4.1...stdlib-v0.4.2) (2021-10-11)
|
|
4
56
|
|
|
5
57
|
|
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2017-
|
|
3
|
+
Copyright (c) 2017-2022 Oscar Spencer <oscar@grain-lang.org> and Philip Blair <philip@grain-lang.org>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/array.gr
CHANGED
|
@@ -30,7 +30,7 @@ let initPtr = () => {
|
|
|
30
30
|
initPtr()
|
|
31
31
|
|
|
32
32
|
@disableGC
|
|
33
|
-
let initLength =
|
|
33
|
+
let initLength = length => {
|
|
34
34
|
let length = WasmI32.fromGrain(length)
|
|
35
35
|
if (WasmI32.eqz(WasmI32.and(length, 1n))) {
|
|
36
36
|
throw Exception.InvalidArgument("Length argument must be an integer")
|
|
@@ -51,8 +51,8 @@ let initLength = (length) => {
|
|
|
51
51
|
* @since v0.1.0
|
|
52
52
|
*/
|
|
53
53
|
@disableGC
|
|
54
|
-
export let rec length =
|
|
55
|
-
let ptr = WasmI32.fromGrain(array: Array<a>)
|
|
54
|
+
export let rec length = array => {
|
|
55
|
+
let ptr = WasmI32.fromGrain(array: (Array<a>))
|
|
56
56
|
let ret = tagSimpleNumber(WasmI32.load(ptr, _ARRAY_LENGTH_OFFSET))
|
|
57
57
|
Memory.decRef(ptr)
|
|
58
58
|
Memory.decRef(WasmI32.fromGrain(length))
|
|
@@ -73,13 +73,21 @@ export let rec length = (array) => {
|
|
|
73
73
|
* @since v0.1.0
|
|
74
74
|
*/
|
|
75
75
|
@disableGC
|
|
76
|
-
export let rec make /*: (Number, a) -> Array<a>*/
|
|
76
|
+
export let rec make /*: (Number, a) -> Array<a>*/ =
|
|
77
|
+
(
|
|
78
|
+
length: Number,
|
|
79
|
+
item: a,
|
|
80
|
+
) => {
|
|
77
81
|
let lengthArg = length
|
|
78
82
|
let length = initLength(length)
|
|
79
83
|
let byteLength = WasmI32.mul(length, 4n)
|
|
80
84
|
let array = allocateArray(length)
|
|
81
85
|
for (let mut i = 0n; WasmI32.ltS(i, byteLength); i = WasmI32.add(i, 4n)) {
|
|
82
|
-
WasmI32.store(
|
|
86
|
+
WasmI32.store(
|
|
87
|
+
WasmI32.add(array, i),
|
|
88
|
+
Memory.incRef(WasmI32.fromGrain(item)),
|
|
89
|
+
_ARRAY_START_OFFSET
|
|
90
|
+
)
|
|
83
91
|
}
|
|
84
92
|
let ret = WasmI32.toGrain(array): (Array<a>)
|
|
85
93
|
Memory.decRef(WasmI32.fromGrain(lengthArg))
|
|
@@ -102,16 +110,24 @@ export let rec make /*: (Number, a) -> Array<a>*/ = (length: Number, item: a) =
|
|
|
102
110
|
* @since v0.1.0
|
|
103
111
|
*/
|
|
104
112
|
@disableGC
|
|
105
|
-
export let rec init /*: (Number, Number -> a) -> Array<a>*/ =
|
|
113
|
+
export let rec init /*: (Number, Number -> a) -> Array<a>*/ =
|
|
114
|
+
(
|
|
115
|
+
length: Number,
|
|
116
|
+
fn: Number -> a,
|
|
117
|
+
) => {
|
|
106
118
|
let length = initLength(length)
|
|
107
119
|
let byteLength = WasmI32.mul(length, 4n)
|
|
108
120
|
let array = allocateArray(length)
|
|
109
121
|
let mut index = 0n
|
|
110
122
|
for (let mut i = 0n; WasmI32.ltS(i, byteLength); i = WasmI32.add(i, 4n)) {
|
|
111
|
-
Memory.incRef(WasmI32.fromGrain(fn))
|
|
123
|
+
Memory.incRef(WasmI32.fromGrain(fn))
|
|
112
124
|
// [FIXME] This line fails the array/map test suite (#815)
|
|
113
125
|
//assert !WasmI32.eqz(WasmI32.and(WasmI32.fromGrain(index), 1n)) // must be a simple int for next line to be correct
|
|
114
|
-
WasmI32.store(
|
|
126
|
+
WasmI32.store(
|
|
127
|
+
WasmI32.add(array, i),
|
|
128
|
+
WasmI32.fromGrain(fn(tagSimpleNumber(index))),
|
|
129
|
+
_ARRAY_START_OFFSET
|
|
130
|
+
)
|
|
115
131
|
//WasmI32.store(WasmI32.add(array, i), WasmI32.fromGrain(4), _ARRAY_START_OFFSET)
|
|
116
132
|
index = WasmI32.add(index, 1n)
|
|
117
133
|
}
|
|
@@ -186,29 +202,29 @@ export let append = (array1, array2) => {
|
|
|
186
202
|
*
|
|
187
203
|
* @since v0.1.0
|
|
188
204
|
*/
|
|
189
|
-
export let concat =
|
|
205
|
+
export let concat = arrays => {
|
|
190
206
|
// This function is slightly verbose to avoid depending on the List stdlib.
|
|
191
207
|
|
|
192
208
|
let rec findLength = (arrays, acc) => {
|
|
193
209
|
match (arrays) {
|
|
194
210
|
[fst, ...rest] => findLength(rest, acc + length(fst)),
|
|
195
|
-
[] => acc
|
|
211
|
+
[] => acc,
|
|
196
212
|
}
|
|
197
213
|
}
|
|
198
214
|
|
|
199
215
|
let mut offset = 0
|
|
200
216
|
let mut arrs = arrays
|
|
201
217
|
|
|
202
|
-
let rec next =
|
|
218
|
+
let rec next = index => {
|
|
203
219
|
let array = match (arrs) {
|
|
204
220
|
[fst, ..._] => fst,
|
|
205
|
-
[] => fail "end of arrays list"
|
|
221
|
+
[] => fail "end of arrays list",
|
|
206
222
|
}
|
|
207
223
|
if (index - offset == length(array)) {
|
|
208
224
|
offset += length(array)
|
|
209
225
|
arrs = match (arrs) {
|
|
210
226
|
[_, ...rest] => rest,
|
|
211
|
-
[] => fail "end of arrays list"
|
|
227
|
+
[] => fail "end of arrays list",
|
|
212
228
|
}
|
|
213
229
|
next(index)
|
|
214
230
|
} else {
|
|
@@ -228,10 +244,28 @@ export let concat = (arrays) => {
|
|
|
228
244
|
*
|
|
229
245
|
* @since v0.1.0
|
|
230
246
|
*/
|
|
231
|
-
export let copy =
|
|
247
|
+
export let copy = array => {
|
|
232
248
|
init(length(array), n => array[n])
|
|
233
249
|
}
|
|
234
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Iterates an array a given number of times, calling an iterator function on each element.
|
|
253
|
+
*
|
|
254
|
+
* @param fn: The iterator function to call with each element
|
|
255
|
+
* @param n: The number of times to iterate the given array
|
|
256
|
+
* @param array: The array to iterate
|
|
257
|
+
*
|
|
258
|
+
* @since v0.4.4
|
|
259
|
+
*/
|
|
260
|
+
export let cycle = (fn, n, array) => {
|
|
261
|
+
let length = length(array)
|
|
262
|
+
for (let mut iteration = 0; iteration < n; iteration += 1) {
|
|
263
|
+
for (let mut count = 0; count < length; count += 1) {
|
|
264
|
+
fn(array[count]): Void
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
235
269
|
/**
|
|
236
270
|
* Iterates an array, calling an iterator function on each element.
|
|
237
271
|
*
|
|
@@ -243,10 +277,8 @@ export let copy = (array) => {
|
|
|
243
277
|
*/
|
|
244
278
|
export let forEach = (fn, array) => {
|
|
245
279
|
let length = length(array)
|
|
246
|
-
let mut count = 0
|
|
247
|
-
while (count < length) {
|
|
280
|
+
for (let mut count = 0; count < length; count += 1) {
|
|
248
281
|
fn(array[count]): Void
|
|
249
|
-
count = incr(count)
|
|
250
282
|
}
|
|
251
283
|
}
|
|
252
284
|
|
|
@@ -262,10 +294,8 @@ export let forEach = (fn, array) => {
|
|
|
262
294
|
*/
|
|
263
295
|
export let forEachi = (fn, array) => {
|
|
264
296
|
let length = length(array)
|
|
265
|
-
let mut count = 0
|
|
266
|
-
|
|
267
|
-
fn(array[count], count): (Void)
|
|
268
|
-
count = incr(count)
|
|
297
|
+
for (let mut count = 0; count < length; count += 1) {
|
|
298
|
+
fn(array[count], count): Void
|
|
269
299
|
}
|
|
270
300
|
}
|
|
271
301
|
|
|
@@ -282,7 +312,7 @@ export let forEachi = (fn, array) => {
|
|
|
282
312
|
*/
|
|
283
313
|
export let map = (fn, array) => {
|
|
284
314
|
let length = length(array)
|
|
285
|
-
init(length,
|
|
315
|
+
init(length, i => {
|
|
286
316
|
fn(array[i])
|
|
287
317
|
})
|
|
288
318
|
}
|
|
@@ -299,7 +329,7 @@ export let map = (fn, array) => {
|
|
|
299
329
|
*/
|
|
300
330
|
export let mapi = (fn, array) => {
|
|
301
331
|
let length = length(array)
|
|
302
|
-
init(length,
|
|
332
|
+
init(length, index => {
|
|
303
333
|
fn(array[index], index)
|
|
304
334
|
})
|
|
305
335
|
}
|
|
@@ -324,7 +354,7 @@ export let mapi = (fn, array) => {
|
|
|
324
354
|
*/
|
|
325
355
|
export let reduce = (fn, initial, array) => {
|
|
326
356
|
let mut acc = initial
|
|
327
|
-
forEach(
|
|
357
|
+
forEach(el => acc = fn(acc, el), array)
|
|
328
358
|
acc
|
|
329
359
|
}
|
|
330
360
|
|
|
@@ -378,7 +408,9 @@ export let flatMap = (fn, array) => {
|
|
|
378
408
|
* @since v0.3.0
|
|
379
409
|
*/
|
|
380
410
|
export let every = (fn, array) => {
|
|
381
|
-
reduce((acc, value) => {
|
|
411
|
+
reduce((acc, value) => {
|
|
412
|
+
acc && fn(value)
|
|
413
|
+
}, true, array)
|
|
382
414
|
}
|
|
383
415
|
|
|
384
416
|
/**
|
|
@@ -392,7 +424,9 @@ export let every = (fn, array) => {
|
|
|
392
424
|
* @since v0.3.0
|
|
393
425
|
*/
|
|
394
426
|
export let some = (fn, array) => {
|
|
395
|
-
reduce((acc, value) => {
|
|
427
|
+
reduce((acc, value) => {
|
|
428
|
+
acc || fn(value)
|
|
429
|
+
}, false, array)
|
|
396
430
|
}
|
|
397
431
|
|
|
398
432
|
/**
|
|
@@ -435,9 +469,12 @@ export let fillRange = (value, start, stop, array) => {
|
|
|
435
469
|
}
|
|
436
470
|
|
|
437
471
|
let mut index = startIndex
|
|
438
|
-
|
|
439
|
-
|
|
472
|
+
for (
|
|
473
|
+
let mut index = startIndex;
|
|
474
|
+
index < stopIndex && index < length;
|
|
440
475
|
index += 1
|
|
476
|
+
) {
|
|
477
|
+
array[index] = value
|
|
441
478
|
}
|
|
442
479
|
void
|
|
443
480
|
}
|
|
@@ -450,9 +487,9 @@ export let fillRange = (value, start, stop, array) => {
|
|
|
450
487
|
*
|
|
451
488
|
* @since v0.4.0
|
|
452
489
|
*/
|
|
453
|
-
export let reverse =
|
|
490
|
+
export let reverse = array => {
|
|
454
491
|
let len = length(array)
|
|
455
|
-
init(len,
|
|
492
|
+
init(len, index => {
|
|
456
493
|
let last = len - index - 1
|
|
457
494
|
array[last]
|
|
458
495
|
})
|
|
@@ -466,7 +503,7 @@ export let reverse = (array) => {
|
|
|
466
503
|
*
|
|
467
504
|
* @since v0.1.0
|
|
468
505
|
*/
|
|
469
|
-
export let toList =
|
|
506
|
+
export let toList = array => {
|
|
470
507
|
let rec buildList = (acc, index) => {
|
|
471
508
|
let index = index - 1
|
|
472
509
|
if (index < 0) {
|
|
@@ -486,22 +523,22 @@ export let toList = (array) => {
|
|
|
486
523
|
*
|
|
487
524
|
* @since v0.1.0
|
|
488
525
|
*/
|
|
489
|
-
export let fromList =
|
|
526
|
+
export let fromList = list => {
|
|
490
527
|
let rec listLength = (list, acc) => {
|
|
491
528
|
match (list) {
|
|
492
529
|
[_, ...rest] => listLength(rest, acc + 1),
|
|
493
|
-
[] => acc
|
|
530
|
+
[] => acc,
|
|
494
531
|
}
|
|
495
532
|
}
|
|
496
533
|
|
|
497
534
|
let mut lst = list
|
|
498
|
-
let rec next =
|
|
535
|
+
let rec next = index => {
|
|
499
536
|
match (lst) {
|
|
500
537
|
[fst, ...rest] => {
|
|
501
538
|
lst = rest
|
|
502
539
|
fst
|
|
503
540
|
},
|
|
504
|
-
[] => next(index)
|
|
541
|
+
[] => next(index),
|
|
505
542
|
}
|
|
506
543
|
}
|
|
507
544
|
init(listLength(list, 0), next)
|
|
@@ -520,11 +557,9 @@ export let fromList = (list) => {
|
|
|
520
557
|
export let contains = (search, array) => {
|
|
521
558
|
// TODO: This should use recursion when we can pattern match arrays
|
|
522
559
|
let len = length(array)
|
|
523
|
-
let mut index = 0
|
|
524
560
|
let mut found = false
|
|
525
|
-
|
|
526
|
-
found =
|
|
527
|
-
index += 1
|
|
561
|
+
for (let mut index = 0; !found && index < len; index += 1) {
|
|
562
|
+
found = array[index] == search
|
|
528
563
|
}
|
|
529
564
|
found
|
|
530
565
|
}
|
|
@@ -540,22 +575,22 @@ export let contains = (search, array) => {
|
|
|
540
575
|
*/
|
|
541
576
|
export let find = (fn, array) => {
|
|
542
577
|
let length = length(array)
|
|
543
|
-
if(length == 0){
|
|
578
|
+
if (length == 0) {
|
|
544
579
|
None
|
|
545
580
|
} else {
|
|
546
581
|
let mut count = 0
|
|
547
582
|
let mut matching = false
|
|
548
583
|
let mut matchedItem = array[0]
|
|
549
584
|
while (count < length) {
|
|
550
|
-
if(fn(array[count])) {
|
|
585
|
+
if (fn(array[count])) {
|
|
551
586
|
matching = true
|
|
552
587
|
matchedItem = array[count]
|
|
553
588
|
count = length
|
|
554
589
|
} else {
|
|
555
|
-
count
|
|
590
|
+
count += 1
|
|
556
591
|
}
|
|
557
592
|
}
|
|
558
|
-
if(!matching) {
|
|
593
|
+
if (!matching) {
|
|
559
594
|
None
|
|
560
595
|
} else {
|
|
561
596
|
Some(matchedItem)
|
|
@@ -574,22 +609,22 @@ export let find = (fn, array) => {
|
|
|
574
609
|
*/
|
|
575
610
|
export let findIndex = (fn, array) => {
|
|
576
611
|
let length = length(array)
|
|
577
|
-
if(length == 0){
|
|
612
|
+
if (length == 0) {
|
|
578
613
|
None
|
|
579
614
|
} else {
|
|
580
615
|
let mut count = 0
|
|
581
616
|
let mut matching = false
|
|
582
617
|
let mut matchedIndex = 0
|
|
583
618
|
while (count < length) {
|
|
584
|
-
if(fn(array[count])) {
|
|
619
|
+
if (fn(array[count])) {
|
|
585
620
|
matching = true
|
|
586
621
|
matchedIndex = count
|
|
587
622
|
count = length
|
|
588
623
|
} else {
|
|
589
|
-
count
|
|
624
|
+
count += 1
|
|
590
625
|
}
|
|
591
626
|
}
|
|
592
|
-
if(!matching) {
|
|
627
|
+
if (!matching) {
|
|
593
628
|
None
|
|
594
629
|
} else {
|
|
595
630
|
Some(matchedIndex)
|
|
@@ -613,8 +648,8 @@ export let product = (array1: Array<a>, array2: Array<b>) => {
|
|
|
613
648
|
let mut indexA = -1
|
|
614
649
|
|
|
615
650
|
init(lenA * lenB, n => {
|
|
616
|
-
if(n % lenB == 0){
|
|
617
|
-
indexA
|
|
651
|
+
if (n % lenB == 0) {
|
|
652
|
+
indexA += 1
|
|
618
653
|
} else {
|
|
619
654
|
indexA = indexA
|
|
620
655
|
}
|
|
@@ -635,12 +670,9 @@ export let count = (fn, array) => {
|
|
|
635
670
|
let length = length(array)
|
|
636
671
|
let mut position = 0
|
|
637
672
|
let mut count = 0
|
|
638
|
-
|
|
639
|
-
if(fn(array[position])) {
|
|
640
|
-
count
|
|
641
|
-
position = incr(position)
|
|
642
|
-
} else {
|
|
643
|
-
position = incr(position)
|
|
673
|
+
for (let mut position = 0; position < length; position += 1) {
|
|
674
|
+
if (fn(array[position])) {
|
|
675
|
+
count += 1
|
|
644
676
|
}
|
|
645
677
|
}
|
|
646
678
|
count
|
|
@@ -658,14 +690,10 @@ export let count = (fn, array) => {
|
|
|
658
690
|
*/
|
|
659
691
|
export let counti = (fn, array) => {
|
|
660
692
|
let length = length(array)
|
|
661
|
-
let mut position = 0
|
|
662
693
|
let mut count = 0
|
|
663
|
-
|
|
664
|
-
if(fn(array[position], position)) {
|
|
665
|
-
count
|
|
666
|
-
position = incr(position)
|
|
667
|
-
} else {
|
|
668
|
-
position = incr(position)
|
|
694
|
+
for (let mut position = 0; position < length; position += 1) {
|
|
695
|
+
if (fn(array[position], position)) {
|
|
696
|
+
count += 1
|
|
669
697
|
}
|
|
670
698
|
}
|
|
671
699
|
count
|
|
@@ -685,13 +713,13 @@ export let counti = (fn, array) => {
|
|
|
685
713
|
export let filter = (fn, array) => {
|
|
686
714
|
let filtered = copy(array)
|
|
687
715
|
let mut position = 0
|
|
688
|
-
forEach(
|
|
716
|
+
forEach(el => {
|
|
689
717
|
if (fn(el)) {
|
|
690
718
|
filtered[position] = el
|
|
691
|
-
position
|
|
719
|
+
position += 1
|
|
692
720
|
}
|
|
693
721
|
}, array)
|
|
694
|
-
init(position,
|
|
722
|
+
init(position, index => {
|
|
695
723
|
filtered[index]
|
|
696
724
|
})
|
|
697
725
|
}
|
|
@@ -713,10 +741,10 @@ export let filteri = (fn, array) => {
|
|
|
713
741
|
forEachi((el, index) => {
|
|
714
742
|
if (fn(el, index)) {
|
|
715
743
|
filtered[position] = el
|
|
716
|
-
position
|
|
744
|
+
position += 1
|
|
717
745
|
}
|
|
718
746
|
}, array)
|
|
719
|
-
init(position,
|
|
747
|
+
init(position, index => {
|
|
720
748
|
filtered[index]
|
|
721
749
|
})
|
|
722
750
|
}
|
|
@@ -730,11 +758,9 @@ export let filteri = (fn, array) => {
|
|
|
730
758
|
*
|
|
731
759
|
* @since v0.3.0
|
|
732
760
|
*/
|
|
733
|
-
export let unique =
|
|
734
|
-
filteri(
|
|
735
|
-
|
|
736
|
-
array
|
|
737
|
-
)
|
|
761
|
+
export let unique = array => {
|
|
762
|
+
filteri((el, index) =>
|
|
763
|
+
findIndex(value => value == el, array) == Some(index), array)
|
|
738
764
|
}
|
|
739
765
|
|
|
740
766
|
/**
|
|
@@ -769,15 +795,17 @@ export let zip = (array1: Array<a>, array2: Array<b>) => {
|
|
|
769
795
|
*
|
|
770
796
|
* @since v0.4.0
|
|
771
797
|
*/
|
|
772
|
-
export let unzip =
|
|
798
|
+
export let unzip = array => {
|
|
773
799
|
let lenArr = length(array)
|
|
774
800
|
|
|
775
801
|
let a = init(lenArr, n => {
|
|
776
|
-
let (fst, _) = array[n]
|
|
802
|
+
let (fst, _) = array[n]
|
|
803
|
+
fst
|
|
777
804
|
})
|
|
778
805
|
|
|
779
806
|
let b = init(lenArr, n => {
|
|
780
|
-
let (_, snd) = array[n]
|
|
807
|
+
let (_, snd) = array[n]
|
|
808
|
+
snd
|
|
781
809
|
})
|
|
782
810
|
|
|
783
811
|
(a, b)
|
|
@@ -796,15 +824,27 @@ export let join = (separator: String, items: Array<String>) => {
|
|
|
796
824
|
let iter = (acc, str) => {
|
|
797
825
|
match (acc) {
|
|
798
826
|
None => Some(str),
|
|
799
|
-
Some(prev) => Some(prev ++ separator ++ str)
|
|
827
|
+
Some(prev) => Some(prev ++ separator ++ str),
|
|
800
828
|
}
|
|
801
829
|
}
|
|
802
|
-
match(reduce(iter, None, items)) {
|
|
830
|
+
match (reduce(iter, None, items)) {
|
|
803
831
|
None => "",
|
|
804
832
|
Some(s) => s,
|
|
805
833
|
}
|
|
806
834
|
}
|
|
807
835
|
|
|
836
|
+
/**
|
|
837
|
+
* A simple helper function to convert a negative array index
|
|
838
|
+
* number to its positive positional equivalent.
|
|
839
|
+
*/
|
|
840
|
+
let wrapNegativeIndex = (arrLen, idx) => {
|
|
841
|
+
if (idx >= 0) {
|
|
842
|
+
idx
|
|
843
|
+
} else {
|
|
844
|
+
arrLen + idx
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
808
848
|
/**
|
|
809
849
|
* Slices an array given zero-based start and end indexes. The value
|
|
810
850
|
* at the end index will not be included in the result.
|
|
@@ -821,17 +861,8 @@ export let join = (separator: String, items: Array<String>) => {
|
|
|
821
861
|
*/
|
|
822
862
|
export let slice = (startIndex, endIndex, array) => {
|
|
823
863
|
let arrayLength = length(array)
|
|
824
|
-
|
|
825
|
-
let
|
|
826
|
-
if (idx >= 0) {
|
|
827
|
-
idx
|
|
828
|
-
} else {
|
|
829
|
-
arrayLength + idx
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
let startIndex = wrapNegativeIndex(startIndex)
|
|
834
|
-
let endIndex = wrapNegativeIndex(endIndex)
|
|
864
|
+
let startIndex = wrapNegativeIndex(arrayLength, startIndex)
|
|
865
|
+
let endIndex = wrapNegativeIndex(arrayLength, endIndex)
|
|
835
866
|
// Ensure we aren't working with an `end` value that is too big
|
|
836
867
|
let endIndex = if (endIndex > arrayLength) {
|
|
837
868
|
arrayLength
|
|
@@ -839,7 +870,7 @@ export let slice = (startIndex, endIndex, array) => {
|
|
|
839
870
|
endIndex
|
|
840
871
|
}
|
|
841
872
|
|
|
842
|
-
let newLength = endIndex - startIndex
|
|
873
|
+
let newLength = endIndex - startIndex
|
|
843
874
|
if (newLength < 0) {
|
|
844
875
|
[>]
|
|
845
876
|
} else if (newLength > arrayLength) {
|
|
@@ -848,3 +879,83 @@ export let slice = (startIndex, endIndex, array) => {
|
|
|
848
879
|
init(newLength, n => array[startIndex + n])
|
|
849
880
|
}
|
|
850
881
|
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Sorts an array in-place.
|
|
885
|
+
*
|
|
886
|
+
* Ordering is calculated using a comparator function which takes two array 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.
|
|
887
|
+
* @param comp: The comparator function used to indicate sort order
|
|
888
|
+
* @param array: The array to be sorted
|
|
889
|
+
* @since v0.4.5
|
|
890
|
+
*/
|
|
891
|
+
export let sort = (comp, array) => {
|
|
892
|
+
let partition = (low, high) => {
|
|
893
|
+
let pivot = array[high]
|
|
894
|
+
let mut i = low - 1
|
|
895
|
+
for (let mut j = low; j < high; j += 1) {
|
|
896
|
+
if (comp(array[j], pivot) < 0) {
|
|
897
|
+
i += 1
|
|
898
|
+
let temp = array[i]
|
|
899
|
+
array[i] = array[j]
|
|
900
|
+
array[j] = temp
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
let temp = array[i + 1]
|
|
904
|
+
array[i + 1] = array[high]
|
|
905
|
+
array[high] = temp
|
|
906
|
+
i + 1
|
|
907
|
+
}
|
|
908
|
+
let rec quicksort = (low, high) => {
|
|
909
|
+
if (low < high) {
|
|
910
|
+
let partitionIndex = partition(low, high)
|
|
911
|
+
quicksort(partitionIndex + 1, high)
|
|
912
|
+
quicksort(low, partitionIndex - 1)
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
let len = length(array)
|
|
916
|
+
quicksort(0, len - 1)
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Rotates an array by n elements to the right, in place.
|
|
921
|
+
*
|
|
922
|
+
* If n is negative, the array will be rotated by n elements
|
|
923
|
+
* to the left. See examples.
|
|
924
|
+
*
|
|
925
|
+
* @param n: The number of elements to rotate by
|
|
926
|
+
* @param arr: The array to be rotated
|
|
927
|
+
*
|
|
928
|
+
* @example let array = [> 1, 2, 3, 4, 5]; rotate(2, arr); arr == [> 4, 5, 1, 2, 3]
|
|
929
|
+
* @example let array = [> 1, 2, 3, 4, 5]; rotate(-1, arr); arr == [> 2, 3, 4, 5, 1]
|
|
930
|
+
* @since v0.4.5
|
|
931
|
+
*/
|
|
932
|
+
export let rotate = (n, arr) => {
|
|
933
|
+
let rec gcd = (a, b) => {
|
|
934
|
+
if (b == 0) {
|
|
935
|
+
a
|
|
936
|
+
} else {
|
|
937
|
+
gcd(b, a % b)
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
let arrLen = length(arr)
|
|
942
|
+
if (arrLen > 0) {
|
|
943
|
+
let k = n % arrLen
|
|
944
|
+
let mut d = -1
|
|
945
|
+
let mut j = 0
|
|
946
|
+
for (let mut i = 0; i < gcd(arrLen, k); i += 1) {
|
|
947
|
+
j = i
|
|
948
|
+
let temp = arr[i]
|
|
949
|
+
while (true) {
|
|
950
|
+
d = (j - k) % arrLen
|
|
951
|
+
if (d == i) {
|
|
952
|
+
break
|
|
953
|
+
}
|
|
954
|
+
let newVal = arr[d]
|
|
955
|
+
arr[j] = newVal
|
|
956
|
+
j = d
|
|
957
|
+
}
|
|
958
|
+
arr[j] = temp
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|