Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Iterator::try_flat_map() method #969

Open
Niedzwiedzw opened this issue Jul 6, 2024 · 2 comments
Open

Proposal: Iterator::try_flat_map() method #969

Niedzwiedzw opened this issue Jul 6, 2024 · 2 comments
Labels
fallible-iterator Iterator of results/options

Comments

@Niedzwiedzw
Copy link

Niedzwiedzw commented Jul 6, 2024

Managed to get it to work with Box<_>, maybe it can be further optimized by defining a custom iterator. I use it a lot, it's very helpful

use std::iter::once;
use tap::prelude::*;

fn boxed_iter<'a, T: 'a>(
    iter: impl Iterator<Item = T> + 'a,
) -> Box<dyn Iterator<Item = T> + 'a> {
    Box::new(iter)
}

#[extension_traits::extension(pub trait IteratorTryFlatMapExt)]
impl<'iter, T, E, I> I
where
    E: 'iter,
    T: 'iter,
    I: Iterator<Item = std::result::Result<T, E>> + 'iter,
{
    fn try_flat_map<U, NewIterator, F>(
        self,
        mut try_flat_map: F,
    ) -> impl Iterator<Item = std::result::Result<U, E>> + 'iter
    where
        U: 'iter,
        NewIterator: Iterator<Item = std::result::Result<U, E>> + 'iter,
        F: FnMut(T) -> NewIterator + 'iter,
    {
        self.flat_map(move |e| match e {
            Ok(value) => value.pipe(&mut try_flat_map).pipe(boxed_iter),
            Err(e) => e.pipe(Err).pipe(once).pipe(boxed_iter),
        })
    }
}
@Niedzwiedzw Niedzwiedzw changed the title Proposal: :Iterator:try_flat_map() method Proposal: Iterator::try_flat_map() method Jul 6, 2024
@Philippe-Cholet Philippe-Cholet added the fallible-iterator Iterator of results/options label Jul 6, 2024
@Philippe-Cholet
Copy link
Member

I am a bit reluctant to add many methods for fallible iterators because it seems to open the door for many many cases.
However, I reckon that this can not be easily written with Itertools::process_results? Something like that maybe

iter.process_results(|t_it| t_it.map(try_flat_map).process_results(|u_it| ...))??

You have an iterator of results then you map the "ok" values to another iterators of results, then this is flattened, am I right?
It seems to do a lot.

Do you have an usage example for this?

@Niedzwiedzw
Copy link
Author

process_results - I've never heard of it, I'll experiment with it, thanks! as for my use case, I needed something like this for recursively iterating a tree of elements and extracting each child is fallible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fallible-iterator Iterator of results/options
Projects
None yet
Development

No branches or pull requests

2 participants