Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert a Vec<Result<T, E>> to Result<Vec<T>, E>? [duplicate]

Tags:

monads

rust

Is there any opinionated and more elegant way to convert Vec<Result<T, E>> to Result<Vec<T>, E>? I want to get Ok<Vec<T>> if all values of vector are Ok<T> and Err<E> if at least one is Err<E>.

Example:

fn vec_of_result_to_result_of_vec<T, E>(v: Vec<Result<T, E>>) -> Result<Vec<T>, E>
where
    T: std::fmt::Debug,
    E: std::fmt::Debug,
{
    let mut new: Vec<T> = Vec::new();

    for el in v.into_iter() {
        if el.is_ok() {
            new.push(el.unwrap());
        } else {
            return Err(el.unwrap_err());
        }
    }

    Ok(new)
}

I'm looking for a more declarative way to write this. This function forces me to write a where clause which will never be used and Err(el.unwrap_err()) looks useless. In other words, the code does many things just to make the compiler happy. I feel like this is such a common case that there's a better way to do it.

like image 463
Arek C. Avatar asked Sep 08 '20 17:09

Arek C.


People also ask

How do I get the first error in Tovec?

use to_vec :: ToVec ; let v = "one two three". split_whitespace (). to_vec (); assert_eq! ( v, & [ "one", "two", "three" ]); There's a specialized form for collecting Result<T,E> into Result<Vec<T>,E>, where the error is the first error encountered.

What is result in C++?

It is an enum with the variants, Ok (T), representing success and containing a value, and Err (E), representing error and containing an error value. Functions return Result whenever errors are expected and recoverable. In the std crate, Result is most prominently used for I/O. A simple function returning Result might be defined and used like so:

What is result<T E> in Swift?

Result<T, E> is the type used for returning and propagating errors. It is an enum with the variants, Ok(T), representing success and containing a value, and Err(E), representing error and containing an error value. enum Result<T, E> { Ok(T), Err(E), }Run. Functions return Result whenever errors are expected and recoverable.


Video Answer


2 Answers

An iterator over Result<T, E> can be collect()-ed directly into a Result<Vec<T>, E>; that is, your entire function can be replaced with:

let new: Result<Vec<T>, E> = v.into_iter().collect()
like image 136
John Ledbetter Avatar answered Oct 13 '22 07:10

John Ledbetter


You can use the FromIterator trait implementation on Result (.collect() requires FromIterator on the destination type and calls into it for the conversion from Iterator):

fn vec_of_result_to_result_of_vec<T, E>(v: Vec<Result<T, E>>) -> Result<Vec<T>, E> {
    v.into_iter().collect()
}
like image 30
chpio Avatar answered Oct 13 '22 07:10

chpio