Hi, I'm new to rust and still learn the ecosystem. The problem I have:
I have a Iterator<Option<T>> and want to collect it to Vec<T> if it only contains no None values. I think I want a function try_collect that transforms Iter<Option<T>> to Option<Vec<T>>. The name try_collect would be fitting, as there is a Option-unaware method collect and other fail-aware functions try_for_each and try_fold.
Is there anything like this in the standard library?
Currently, I create a list outside the iterator and insert the elements using try_for_each. Then, the collection is only returned if try_for_each was successful
fn try_collect(iterator: Iterator<Option<T>>) -> Option<Vec<T>> {
let mut ts = Vec::new();
let success = iterator.try_for_each(|t| t.map(|t| ts.push(t)))
match success {
Some(()) => Some(ts)
None => None
}
}
I think collect should just work with an Option target:
fn main() {
let not_all = vec![Some(2), Some(3), None];
let all = vec![Some(2), Some(3), Some(4)];
let collected_not_all: Option<Vec<_>> =
not_all.into_iter().collect();
let collected_all: Option<Vec<_>> =
all.into_iter().collect();
println!("not all: {:?}", collected_not_all);
println!("all: {:?}", collected_all);
}
gives me
not all: None
all: Some([2, 3, 4])
Unless I'm missing something.
Edit: This is because you can collect into anything implementing FromIterator, and there is one for Option collection targets from iterators that produce Option values.
Yes, collecting to Option<C> or Result<C, E> both have this behavior of collecting to any C with Some or Ok items, but stopping on the first None or Err.
This keeps coming up on IRC, too. The FromIterator implementations for Option & Result seems to be one of those things that you cannot find unless you already know it exists.
I think it'd be worth having try_collect just for the clarity, documentability, and findability it would bring.
I'm not surprised many newcomers don't find this for themselves. As a newbie myself I thought I would try to find it in the API documentation.
When you look at the API page for Option, it does list impl<A, V> FromIterator<Option<A>> for Option<V> under Trait Implementations. However in that section, the descriptions are hidden by default, you have to expand with the '+' to see the details. Easy to overlook.