aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Attard <robert.attard@mail.mcgill.ca>2021-07-12 09:51:14 -0400
committerLouis Pilfold <louis@lpil.uk>2021-07-13 17:11:38 +0100
commit42daa4dd149d33e99dc92d0b701132eb92b48000 (patch)
tree147780a0d80608b1af5c0f5777293958e458da12 /src
parentb9200d18f54a6f7aa3bf2fbda2782ab84a2289f9 (diff)
downloadgleam_stdlib-42daa4dd149d33e99dc92d0b701132eb92b48000.tar.gz
gleam_stdlib-42daa4dd149d33e99dc92d0b701132eb92b48000.zip
iterator.fold_until
Diffstat (limited to 'src')
-rw-r--r--src/gleam/iterator.gleam45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/gleam/iterator.gleam b/src/gleam/iterator.gleam
index 25cc441..414956d 100644
--- a/src/gleam/iterator.gleam
+++ b/src/gleam/iterator.gleam
@@ -1036,3 +1036,48 @@ if erlang {
|> Iterator
}
}
+
+fn do_fold_until(
+ continuation: fn() -> Action(e),
+ f: fn(e, acc) -> list.ContinueOrStop(acc),
+ accumulator: acc,
+) -> acc {
+ case continuation() {
+ Stop -> accumulator
+ Continue(elem, next) ->
+ case f(elem, accumulator) {
+ list.Continue(accumulator) -> do_fold_until(next, f, accumulator)
+ list.Stop(accumulator) -> accumulator
+ }
+ }
+}
+
+/// Like `fold`, `fold_until` reduces an iterator of elements into a single value by calling a given
+/// function on each element in turn, but uses a `list.ContinueOrStop` to determine
+/// whether or not to keep iterating.
+///
+/// If called on an iterator of infinite length then this function will only ever
+/// return if the give function returns list.Stop.
+///
+///
+/// ## Examples
+/// > let f = fn(e, acc) {
+/// > case e {
+/// > _ if e < 4 -> list.Continue(e + acc)
+/// > _ -> list.Stop(acc)
+/// > }
+/// > }
+/// >
+/// > [1, 2, 3, 4]
+/// > |> from_list
+/// > |> iterator.fold_until(from: acc, with: f)
+/// 6
+///
+pub fn fold_until(
+ over iterator: Iterator(e),
+ from initial: acc,
+ with f: fn(e, acc) -> list.ContinueOrStop(acc),
+) -> acc {
+ iterator.continuation
+ |> do_fold_until(f, initial)
+}