aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--src/gleam/iterator.gleam31
-rw-r--r--test/gleam/iterator_test.gleam25
3 files changed, 58 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ccebdd..34d64c5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,8 +10,8 @@
- The `dynamic` module gains the `option` function.
- The `uri` module gains the `percent_encode` and `percent_decode` functions.
- The `os` module gains the `erlang_timestamp` function.
-- The `iterator` module gains the `append`, `flatten`, `flat_map` and `step`
- functions.
+- The `iterator` module gains the `append`, `flatten`, `flat_map`, `step`,
+ and `find` functions.
## v0.11.0 - 2020-08-22
diff --git a/src/gleam/iterator.gleam b/src/gleam/iterator.gleam
index e75b0a7..81ef2ce 100644
--- a/src/gleam/iterator.gleam
+++ b/src/gleam/iterator.gleam
@@ -463,3 +463,34 @@ pub fn range(from start: Int, to stop: Int) -> Iterator(Int) {
|> do_range(start, stop, _)
|> Iterator
}
+
+/// Find the first element in a given iterator for which the given function returns
+/// True.
+///
+/// Returns `Error(Nil)` if the function does not return True for any of the
+/// elements.
+///
+/// ## Examples
+///
+/// > find(from_list([1, 2, 3]), fn(x) { x > 2 })
+/// Ok(3)
+///
+/// > find(from_list([1, 2, 3]), fn(x) { x > 4 })
+/// Error(Nil)
+///
+/// > find(from_list([]), fn(x) { True })
+/// Error(Nil)
+///
+pub fn find(
+ in haystack: Iterator(a),
+ one_that is_desired: fn(a) -> Bool,
+) -> Result(a, Nil) {
+ case haystack.continuation() {
+ Continue(element, continuation) ->
+ case is_desired(element) {
+ True -> Ok(element)
+ False -> find(Iterator(continuation), is_desired)
+ }
+ Stop -> Error(Nil)
+ }
+}
diff --git a/test/gleam/iterator_test.gleam b/test/gleam/iterator_test.gleam
index 426c9f7..0f836c6 100644
--- a/test/gleam/iterator_test.gleam
+++ b/test/gleam/iterator_test.gleam
@@ -225,3 +225,28 @@ pub fn drop_test() {
|> iterator.to_list
|> should.equal([5, 6, 7, 8, 9])
}
+
+type Cat {
+ Cat(id: Int)
+}
+
+pub fn find_test() {
+ iterator.range(0, 10)
+ |> iterator.find(fn(e) { e == 5 })
+ |> should.equal(Ok(5))
+
+ iterator.range(0, 10)
+ |> iterator.find(fn(e) { e > 10 })
+ |> should.equal(Error(Nil))
+
+ iterator.from_list([])
+ |> iterator.find(fn(_x) { True })
+ |> should.equal(Error(Nil))
+
+ iterator.unfold(
+ Cat(id: 1),
+ fn(cat: Cat) { iterator.Next(cat, Cat(id: cat.id + 1)) },
+ )
+ |> iterator.find(fn(cat: Cat) { cat.id == 10 })
+ |> should.equal(Ok(Cat(id: 10)))
+}