Skip to content

flatten_ok #522

Closed
Closed
@vadixidav

Description

@vadixidav

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:

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 libcore first?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions