#Collect errors, too

12 messages · Page 1 of 1 (latest)

blazing ether
#

I recently found myself in a situation where I had to either collect all values if none of them had an error, or collect all errors. Since I didn't want to fast-fail through collecting to Result<Vec<T>, E>, I made a function which collects to Result<Vec<T>, Vec<E>>:

fn collect_or_errors<I, T, E>(iter: I) -> Result<Vec<T>, Vec<E>>
where
    I: Iterator<Item = Result<T, E>>,
{
    iter.fold(Ok(Vec::new()), |mut until_now, new| {
        match (&mut until_now, new) {
            (Ok(okays), Ok(new)) => okays.push(new),
            (Err(errors), Err(new)) => errors.push(new),
            (Ok(_), Err(error)) => until_now = Err(vec![error]),
            _ => (),
        };
        until_now
    })
}

fn main() {
    let iter = vec![Err("meow"), Ok(2), Err("doge"), Ok(7), Ok(30)].into_iter();

    let _ = dbg!(collect_or_errors(iter));
}

Two specific things, feel free to note any else, too:

  • Can I make this function more generic, like allowing FromIterator instead of the Vecs? I don't think so, since I need some kind of buffer to actuallly push to, but that may just be me.
  • The match looks pretty convoluted, can I make it any simpler than it already is?
drifting ravine
#

Itertools has a .partition_result() which looks like it does exactly what you want. You would just see if the error collection has any items in it

blazing ether
blazing ether
#

Okay, thanks! That may suffice, though I'll ignore one of those values a lot

#

(also my version allows me to .map_err into an appropiate error and then ? nicely)

drifting ravine
drifting ravine
blazing ether
#

Not necessarily, if I need all errors collected before throwing them into a compile error, for example

drifting ravine
blazing ether
#

...alright

#

Thanks!