-
Notifications
You must be signed in to change notification settings - Fork 23
Closed
Labels
ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)API Change Proposal is accepted (seconded with no objections)T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard librariesA proposal to add or alter unstable APIs in the standard libraries
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.
tv42Scripter17 and LucaCappelletti94
Metadata
Metadata
Assignees
Labels
ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)API Change Proposal is accepted (seconded with no objections)T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard librariesA proposal to add or alter unstable APIs in the standard libraries