Skip to content

Commit 955226b

Browse files
sportolpil
authored andcommitted
Add list.index_fold
1 parent b8000c4 commit 955226b

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
- The `result` module gains the `lazy_or`, `lazy_unwrap`, and `replace_error` functions.
88
- The `bool` module gains the `nand`, `nor`, `exclusive_nor`, and `exclusive_or` functions.
99
- The `bit_builder` module gains the `from_string_builder` function.
10-
- The `list` modules gains the `permutations` function.
10+
- The `list` modules gains the `index_fold`, and `permutations` functions.
1111
- Breaking change in `queue.from_list`. The head element in the list becomes the first element in the queue.
1212
- Fix `queue.pop_back` and `queue.pop_front`
1313

src/gleam/list.gleam

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,46 @@ pub fn fold_right(list: List(a), from initial: b, with fun: fn(a, b) -> b) -> b
454454
}
455455
}
456456

457+
/// Like fold but the folding function also receives the index of the current element.
458+
///
459+
/// ## Examples
460+
///
461+
/// ```
462+
/// ["a", "b", "c"]
463+
/// |> list.index_fold([], fn(index, item, acc) { ... })
464+
/// ```
465+
///
466+
pub fn index_fold(
467+
over over: List(a),
468+
from initial: b,
469+
with fun: fn(Int, a, b) -> b,
470+
) -> b {
471+
over
472+
|> index_map(fn(ix, value) { tuple(ix, value) })
473+
|> fold(
474+
from: initial,
475+
with: fn(t, acc) {
476+
let tuple(ix, val) = t
477+
fun(ix, val, acc)
478+
},
479+
)
480+
}
481+
482+
pub fn try_fold(
483+
over collection: List(a),
484+
from accumulator: b,
485+
with fun: fn(a, b) -> Result(b, b),
486+
) -> b {
487+
case collection {
488+
[] -> accumulator
489+
[first, ..rest] ->
490+
case fun(first, accumulator) {
491+
Ok(next_accumulator) -> try_fold(rest, next_accumulator, fun)
492+
Error(b) -> b
493+
}
494+
}
495+
}
496+
457497
/// Find the first element in a given list for which the given function returns
458498
/// True.
459499
///

test/gleam/list_test.gleam

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ pub fn fold_right_test() {
171171
|> should.equal([1, 2, 3])
172172
}
173173

174+
pub fn index_fold_test() {
175+
["a", "b", "c"]
176+
|> list.index_fold([], fn(ix, i, acc) { [tuple(ix, i), ..acc] })
177+
|> should.equal([tuple(2, "c"), tuple(1, "b"), tuple(0, "a")])
178+
}
179+
174180
pub fn find_map_test() {
175181
let f = fn(x) {
176182
case x {

0 commit comments

Comments
 (0)