168. collect::<Result<Vec<_>, _>>() — Bail an Iterator on the First Error
You have a Vec<&str> of numbers to parse and you want to bail the moment one of them is malformed. The hand-rolled loop with ? works, but collect() does the same thing in one line — and most people never realize the trick is in the turbofish.
The pain point is everywhere: parse a row of CSV cells, deserialize a batch of records, convert a list of paths — any time you map a fallible function over an iterator and want the first failure to stop the show.
The naive version builds the Vec by hand and threads ? through a loop:
| |
The same thing in one line, by asking collect to produce a Result<Vec<_>, _> instead of a Vec<Result<_, _>>:
| |
That works because Result<C, E> (where C: FromIterator<T>) implements FromIterator<Result<T, E>>: feed it an iterator of Results and it yields a single Result. The first Err short-circuits the rest of the iteration; if every item is Ok, you get Ok(collection) back.
| |
The same impl exists for Option, so collect::<Option<Vec<_>>>() bails on the first None:
| |
You’re not stuck with Vec either — any FromIterator target works, so Result<HashSet<_>, _> or Result<String, _> from a Chars iterator is just as valid.
Use it whenever you’d otherwise write a fold-the-error loop. The intent reads off the type signature, and the iterator stops cold at the first bad item instead of finishing the parse and then sifting through a Vec<Result<_, _>> afterwards.