-
Couldn't load subscription status.
- Fork 335
Description
Proposal
I propose adding the following (without the impl Iterator, just to demonstrate):
fn flatten_ok<A, B, E>(self) -> impl Iterator<Item=Result<B, E>>
where Self: Iterator<Item = Result<A, E>>, A: IntoIterator<Item = B>
{...}flatten_ok operates on an iterator of Result<A, E> where A: IntoIterator<Item = B>. If the iterator produces Ok, the value is flattened. If the iterator produces Err, the value is produced exactly as-is.
Why add this?
Several others have been trying to solve this exact problem:
- https://paulkernfeld.com/2018/11/03/flatten-nested-iterator-result.html
- https://stackoverflow.com/questions/59852161/how-to-handle-result-in-flat-map
I also encountered this problem and was unable to find a combinator for this purpose, which was surprising to me.
Potential way to implement
It could be implemented this way:
fn flatten_ok<A, B, E>(self) -> impl Iterator<Item=Result<B, E>>
where Self: Iterator<Item = Result<A, E>>, A: IntoIterator<Item = B>
{
self.flat_map(|res| Either::from(res)
.map_right(|ok| ok.into_iter().map(Ok))
.map_left(Err)
.map_left(std::iter::once)
)
}Of course, a struct could be created within itertools to implement the Iterator so there is no external API dependency on either, and so we can still specify a concrete return type, but the above would approximately the implementation used and does work if this signature (with impl Iterator) is acceptable.
Questions
- Is there another and more clear way to implement this that others are missing? If so, please let me know.
- Should this be proposed to
libcorefirst?