diff options
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | src/gleam/iterator.gleam | 42 | ||||
-rw-r--r-- | test/gleam/iterator_test.gleam | 14 |
3 files changed, 57 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index e155689..308ae7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## v0.17.1 - 2021-09-15 - `uri.parse` now returns a result. +- The `iterator` module gains the `at` function. ## v0.17.0 - 2021-09-11 diff --git a/src/gleam/iterator.gleam b/src/gleam/iterator.gleam index 05bf331..42ef635 100644 --- a/src/gleam/iterator.gleam +++ b/src/gleam/iterator.gleam @@ -1113,3 +1113,45 @@ pub fn try_fold( iterator.continuation |> do_try_fold(f, initial) } + +fn try_yield(continuation: fn() -> Action(e)) -> Result(e, Nil) { + case continuation() { + Stop -> Error(Nil) + Continue(e, _) -> Ok(e) + } +} + +fn do_at(continuation: fn() -> Action(e), index: Int) -> Result(e, Nil) { + case index > 0 { + False -> try_yield(continuation) + True -> + case continuation() { + Stop -> Error(Nil) + Continue(_, next) -> do_at(next, index - 1) + } + } +} + +/// Returns nth element yielded by the given iterator, where 0 means the first element. +/// +/// If there are not enough elements in the iterator, `Error(Nil)` is returned. +/// +/// For any `index` less than 0 this function behaves as if it was set to 0. +/// +/// ## Examples +/// +/// ``` +/// > from_list([1, 2, 3, 4]) |> at(2) +/// Ok(3) +/// +/// > from_list([1, 2, 3, 4]) |> at(4) +/// Error(Nil) +/// +/// > empty() |> iterator.at(0) +/// Error(Nil) +/// ``` +/// +pub fn at(in iterator: Iterator(e), get index: Int) -> Result(e, Nil) { + iterator.continuation + |> do_at(index) +} diff --git a/test/gleam/iterator_test.gleam b/test/gleam/iterator_test.gleam index 2debc51..e7f749a 100644 --- a/test/gleam/iterator_test.gleam +++ b/test/gleam/iterator_test.gleam @@ -481,3 +481,17 @@ pub fn try_fold_test() { |> iterator.try_fold(0, f) |> should.equal(Error("tried to add an odd number")) } + +pub fn at_test() { + iterator.from_list([1, 2, 3, 4]) + |> iterator.at(2) + |> should.equal(Ok(3)) + + iterator.from_list([1, 2, 3, 4]) + |> iterator.at(4) + |> should.equal(Error(Nil)) + + iterator.empty() + |> iterator.at(0) + |> should.equal(Error(Nil)) +} |