Skip to content

Commit

Permalink
Rollup merge of #71899 - cuviper:try_find_map, r=dtolnay
Browse files Browse the repository at this point in the history
Refactor `try_find` a little

~~This works like `find_map`, but mapping to a `Try` type. It stops when `Ok` is `Some(value)`, with an additional short-circuit on `Try::Error`. This is similar to the unstable `try_find`, but has the advantage of being able to directly return the user's `R: Try` type directly, rather than converting to `Result`.~~
(removed -- `try_find_map` was declined in review)

This PR also refactors `try_find` a little to match style. The `E` type parameter was unnecessary, so it's now removed. The folding closure now has reduced parametricity on just `T = Self::Item`, rather
than the whole `Self` iterator type. There's otherwise no functional change in this.
  • Loading branch information
Manishearth authored Jun 20, 2020
2 parents 203305d + db0d70e commit 5c9cd82
Showing 1 changed file with 18 additions and 11 deletions.
29 changes: 18 additions & 11 deletions src/libcore/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2265,7 +2265,7 @@ pub trait Iterator {
}

/// Applies function to the elements of iterator and returns
/// the first non-none result or the first error.
/// the first true result or the first error.
///
/// # Examples
///
Expand All @@ -2286,19 +2286,26 @@ pub trait Iterator {
/// ```
#[inline]
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
fn try_find<F, E, R>(&mut self, mut f: F) -> Result<Option<Self::Item>, E>
fn try_find<F, R>(&mut self, f: F) -> Result<Option<Self::Item>, R::Error>
where
Self: Sized,
F: FnMut(&Self::Item) -> R,
R: Try<Ok = bool, Error = E>,
{
self.try_fold((), move |(), x| match f(&x).into_result() {
Ok(false) => LoopState::Continue(()),
Ok(true) => LoopState::Break(Ok(x)),
Err(x) => LoopState::Break(Err(x)),
})
.break_value()
.transpose()
R: Try<Ok = bool>,
{
#[inline]
fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> LoopState<(), Result<T, R::Error>>
where
F: FnMut(&T) -> R,
R: Try<Ok = bool>,
{
move |(), x| match f(&x).into_result() {
Ok(false) => LoopState::Continue(()),
Ok(true) => LoopState::Break(Ok(x)),
Err(x) => LoopState::Break(Err(x)),
}
}

self.try_fold((), check(f)).break_value().transpose()
}

/// Searches for an element in an iterator, returning its index.
Expand Down

0 comments on commit 5c9cd82

Please sign in to comment.