aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcin Puc <marcin.e.puc@gmail.com>2021-03-21 12:02:30 +0100
committerLouis Pilfold <louis@lpil.uk>2021-04-13 10:50:44 +0100
commitffeb3757f291dbff55c772b7d622e22dac79352c (patch)
tree7c301008788f1ba91d1b7d41599461a065301c3c /src
parent593eeae98d21da64d0e6a956413d3874fe762369 (diff)
downloadgleam_stdlib-ffeb3757f291dbff55c772b7d622e22dac79352c.tar.gz
gleam_stdlib-ffeb3757f291dbff55c772b7d622e22dac79352c.zip
Add {iterator. list}.reduce
Diffstat (limited to 'src')
-rw-r--r--src/gleam/iterator.gleam35
-rw-r--r--src/gleam/list.gleam24
2 files changed, 55 insertions, 4 deletions
diff --git a/src/gleam/iterator.gleam b/src/gleam/iterator.gleam
index f9e39bb..fa49b87 100644
--- a/src/gleam/iterator.gleam
+++ b/src/gleam/iterator.gleam
@@ -115,12 +115,12 @@ pub fn from_list(list: List(element)) -> Iterator(element) {
// Consuming Iterators
fn do_fold(
continuation: fn() -> Action(e),
- initial: acc,
f: fn(e, acc) -> acc,
+ accumulator: acc,
) -> acc {
case continuation() {
- Continue(element, iterator) -> do_fold(iterator, f(element, initial), f)
- Stop -> initial
+ Continue(elem, next) -> do_fold(next, f, f(elem, accumulator))
+ Stop -> accumulator
}
}
@@ -146,7 +146,7 @@ pub fn fold(
with f: fn(e, acc) -> acc,
) -> acc {
iterator.continuation
- |> do_fold(initial, f)
+ |> do_fold(f, initial)
}
// TODO: test
@@ -919,3 +919,30 @@ pub fn group(
|> fold(map.new(), group_updater(key))
|> map.map_values(fn(_, group) { list.reverse(group) })
}
+
+/// This function acts similar to fold, but does not take an initial state.
+/// Instead, it starts from the first yielded element
+/// and combines it with each subsequent element in turn using the given function.
+/// The function is called as f(current_element, accumulator).
+///
+/// Returns `Ok` to indicate a successful run, and `Error` if called on an empty iterator.
+///
+/// ## Examples
+///
+/// > from_list([]) |> reduce(fn(x, y) { x + y })
+/// Error(Nil)
+///
+/// > from_list([1, 2, 3, 4, 5]) |> reduce(fn(x, y) { x + y })
+/// Ok(15)
+///
+pub fn reduce(
+ over iterator: Iterator(e),
+ with f: fn(e, e) -> e,
+) -> Result(e, Nil) {
+ case iterator.continuation() {
+ Stop -> Error(Nil)
+ Continue(e, next) ->
+ do_fold(next, f, e)
+ |> Ok
+ }
+}
diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam
index cb7d940..972da23 100644
--- a/src/gleam/list.gleam
+++ b/src/gleam/list.gleam
@@ -1377,3 +1377,27 @@ fn do_sized_chunk(
pub fn sized_chunk(in list: List(a), into count: Int) -> List(List(a)) {
do_sized_chunk(list, count, count, [], [])
}
+
+/// This function acts similar to fold, but does not take an initial state.
+/// Instead, it starts from the first element in the list
+/// and combines it with each subsequent element in turn using the given function.
+/// The function is called as fun(current_element, accumulator).
+///
+/// Returns `Ok` to indicate a successful run, and `Error` if called on an empty list.
+///
+/// ## Examples
+///
+/// > [] |> reduce(fn(x, y) { x + y })
+/// Error(Nil)
+///
+/// > [1, 2, 3, 4, 5] |> reduce(fn(x, y) { x + y })
+/// Ok(15)
+///
+pub fn reduce(over list: List(a), with fun: fn(a, a) -> a) -> Result(a, Nil) {
+ case list {
+ [] -> Error(Nil)
+ [head, ..tail] ->
+ fold(tail, head, fun)
+ |> Ok
+ }
+}