• Yujiri@lemmy.ml
    link
    fedilink
    arrow-up
    6
    ·
    3 years ago

    Uh… what?

    So I understand the type signature she’s asking for is Iter<Result<T, E>> -> Result<Iter<T>, Iter<E>>

    This suggestion could really use some use case examples. It sounds sufficiently obscure to me that I wouldn’t complain about having to write my own a function for this

    Also, where does the name evert come from?

    • Ephera@lemmy.ml
      link
      fedilink
      arrow-up
      1
      ·
      edit-2
      3 years ago

      I can see this being useful for parsing. You often want to report all of the parsing errors to the user in one go, so collecting them into a list or iterator is useful.

      But yeah, still relatively obscure.

      And I’m guessing, “evert” is simply the respective English word: https://en.wiktionary.org/wiki/evert
      As a non-native speaker, I didn’t know that word either…

  • nutomic@lemmy.mlM
    link
    fedilink
    arrow-up
    3
    ·
    3 years ago

    I think she is talking about this functionality which already exists. It is not very intuitive though.

    let res = my_collection
    .iter()
    .map(|x| method_that_returns_result(x))
    .collect::<Result<Vec<T>, Error>>()?;
    

    So it turns a Vec<Result, Error> into Result<Vec<T>, Error>, and you can turn it into Vec<T> simply with ?. Otherwise you would probably need a for loop.

    • Mad@sopuli.xyz
      link
      fedilink
      arrow-up
      0
      ·
      3 years ago

      do you mean Vec<Result<T, Error>>? why would an error type be the second type argument for a Vec?

  • Aode (He/They)@lemmy.ml
    link
    fedilink
    arrow-up
    1
    ·
    edit-2
    3 years ago

    i might try

    let res = collection.into_iter().map(|item| item.fallible_operation()).fold(Ok(Vec::new()), |acc, res| {
        match (acc, res) {
            (Ok(mut vec), Ok(item)) => {
                vec.push(item);
                Ok(vec)
            (Err(mut vec), Err(error)) => {
                vec.push(error);
                Err(vec)
            }
            (Ok(_), Err(error)) => Err(vec![error]),
            _ => acc,
        }
    });
    

    Maybe expand it with

    pub trait Evert<T, E> {
        fn evert(self) -> Result<Vec<T>, Vec<E>>;
    }
    
    impl<I, T, E> Evert<T, E> for I
    where
        I: IntoIterator<Item = Result<T, E>>,
    {
        fn evert(self) -> Result<Vec<T>, Vec<E>> {
            self.into_iter().fold(/* implementation from above */)
        }
    }
    
    fn main() {
        let result = vec![Ok(1), Err(3), Ok(4), Err(8)].evert();
        assert_eq!(result, Err(vec![3, 8]));
    }