Closed
Description
Proposal
Problem statement
Currently there is no simple way to use all()
, any()
, position()
and rposition()
if the predicate can fail, returning an Err
.
Motivating examples or use cases
This proposal came from an StackOverflow question, which asks for a fallible method for position()
. The answer is rather convoluted when compared to the simplicity of try_for_each()
versus for_each()
.
The original question is:
let items: &[Result<&str, u32>] = &[Ok("foo"), Err(444), Ok("bar")];
let bar_idx = items.iter()
.position(|item| item? == "bar")?; // what to do here?
Solution sketch
I sketched a FooIterator
with the aforementioned methods so I could use them right away, but I suppose they should be members of Iterator
. Also, I'm aware the implementation below is far from being standardized:
pub trait FooIterator: Iterator {
fn try_all<E, F>(&mut self, mut predicate: F) -> Result<bool, E>
where Self: Sized,
F: FnMut(Self::Item) -> Result<bool, E>,
{
for item in self {
if !predicate(item)? {
return Ok(false)
}
}
Ok(true)
}
fn try_any<E, F>(&mut self, mut predicate: F) -> Result<bool, E>
where Self: Sized,
F: FnMut(Self::Item) -> Result<bool, E>,
{
for item in self {
if predicate(item)? {
return Ok(true)
}
}
Ok(false)
}
fn try_position<E, F>(&mut self, mut predicate: F) -> Result<Option<usize>, E>
where Self: Sized,
F: FnMut(Self::Item) -> Result<bool, E>,
{
for (idx, item) in self.enumerate() {
if predicate(item)? {
return Ok(Some(idx));
}
}
Ok(None)
}
fn try_rposition<E, F>(&mut self, mut predicate: F) -> Result<Option<usize>, E>
where Self: Sized + DoubleEndedIterator,
F: FnMut(Self::Item) -> Result<bool, E>,
{
for (idx, item) in self.rev().enumerate() {
if predicate(item)? {
return Ok(Some(idx));
}
}
Ok(None)
}
}
impl<'a, T> TryIterator for core::slice::Iter<'a, T> {}
impl<I> TryIterator for std::iter::Enumerate<I> where I: Iterator {}
impl<I> TryIterator for std::iter::Skip<I> where I: Iterator {}
impl<I> TryIterator for std::iter::StepBy<I> where I: Iterator {}
impl<I> TryIterator for std::iter::Take<I> where I: Iterator {}
Alternatives
I implemented and published the TryIterator
crate, so I could use these methods immediately. But I believe these methods have their place in the standard library.