Skip to content

Commit 2168f6a

Browse files
authored
feat(stdlib): Improve performance in Array & List modules (#1487)
feat(stdlib): Improve performance of `flatMap`, `some`, and `every` functions in Array module feat(stdlib): Improve performance of `some` and `every` functions in List module
1 parent 0c1eb73 commit 2168f6a

File tree

3 files changed

+41
-19
lines changed

3 files changed

+41
-19
lines changed

stdlib/array.gr

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,19 @@ export let reducei = (fn, initial, array) => {
425425
* @since v0.3.0
426426
*/
427427
export let flatMap = (fn, array) => {
428-
reduce((result, value) => append(result, fn(value)), [>], array)
428+
let nested = map(fn, array)
429+
let arrLen = reduce((acc, arr) => acc + length(arr), 0, nested)
430+
let mut outerI = 0
431+
let mut innerI = 0
432+
init(arrLen, i => {
433+
if (innerI >= length(nested[outerI])) {
434+
innerI = 0
435+
outerI += 1
436+
}
437+
let res = nested[outerI][innerI]
438+
innerI += 1
439+
res
440+
})
429441
}
430442

431443
/**
@@ -439,9 +451,12 @@ export let flatMap = (fn, array) => {
439451
* @since v0.3.0
440452
*/
441453
export let every = (fn, array) => {
442-
reduce((acc, value) => {
443-
acc && fn(value)
444-
}, true, array)
454+
let len = length(array)
455+
let mut all = true
456+
for (let mut index = 0; all && index < len; index += 1) {
457+
all = fn(array[index])
458+
}
459+
all
445460
}
446461

447462
/**
@@ -455,9 +470,12 @@ export let every = (fn, array) => {
455470
* @since v0.3.0
456471
*/
457472
export let some = (fn, array) => {
458-
reduce((acc, value) => {
459-
acc || fn(value)
460-
}, false, array)
473+
let len = length(array)
474+
let mut found = false
475+
for (let mut index = 0; !found && index < len; index += 1) {
476+
found = fn(array[index])
477+
}
478+
found
461479
}
462480

463481
/**

stdlib/array.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ No other changes yet.
550550
</details>
551551

552552
```grain
553-
flatMap : ((a -> Array<b>), Array<a>) -> Array<b>
553+
flatMap : ((b -> Array<a>), Array<b>) -> Array<a>
554554
```
555555

556556
Produces a new array by calling a function on each element
@@ -562,14 +562,14 @@ Parameters:
562562

563563
|param|type|description|
564564
|-----|----|-----------|
565-
|`fn`|`a -> Array<b>`|The function to be called on each element, where the value returned will be an array that gets appended to the new array|
566-
|`array`|`Array<a>`|The array to iterate|
565+
|`fn`|`b -> Array<a>`|The function to be called on each element, where the value returned will be an array that gets appended to the new array|
566+
|`array`|`Array<b>`|The array to iterate|
567567

568568
Returns:
569569

570570
|type|description|
571571
|----|-----------|
572-
|`Array<b>`|The new array|
572+
|`Array<a>`|The new array|
573573

574574
### Array.**every**
575575

stdlib/list.gr

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,12 @@ export let rec flatMap = (fn, list) => {
230230
*
231231
* @since v0.1.0
232232
*/
233-
export let every = (fn, list) => {
234-
reduce((acc, value) => {
235-
acc && fn(value)
236-
}, true, list)
233+
export let rec every = (fn, list) => {
234+
match (list) {
235+
[] => true,
236+
// The short-circuiting of `&&` makes this tail-recursive
237+
[first, ...rest] => fn(first) && every(fn, rest),
238+
}
237239
}
238240

239241
/**
@@ -246,10 +248,12 @@ export let every = (fn, list) => {
246248
*
247249
* @since v0.1.0
248250
*/
249-
export let some = (fn, list) => {
250-
reduce((acc, value) => {
251-
acc || fn(value)
252-
}, false, list)
251+
export let rec some = (fn, list) => {
252+
match (list) {
253+
[] => false,
254+
// The short-circuiting of `||` makes this tail-recursive
255+
[first, ...rest] => fn(first) || some(fn, rest),
256+
}
253257
}
254258

255259
/**

0 commit comments

Comments
 (0)