I would like to do something like this:
enum MyEnum {
Foo(Vec<Stuff>),
// ...
}
impl MyEnum {
fn do_sth(&self) -> Result<Bar, E> {
match *self {
MyEnum::Foo(ref vec) => {
let (a, b): (Vec<A>, Vec<B>) = vec
.iter()
.map(|thing| thing.make_a_tuple(arg)) // returns Result<(A, B), E>
.collect::<Result<_, _>>()? // stop on first error
.unzip();
// use a and b
}
// other cases
}
// ...
}
}
This fails to compile with error: the type of this value must be known in this context
.
Through trial and error, I got it to compile like this
fn do_sth(&self) -> Result<Bar, E> {
match *self {
MyEnum::Foo(ref vec) => {
let (a, b): (Vec<A>, Vec<B>) = vec
.iter()
.map(|thing| thing.make_a_tuple(arg))
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.unzip();
// use a and b
}
// other cases
}
}
However, I would like to avoid the unnecessary allocation of a Vec<(A, B)>
.
Is it possible to do this without intermediate allocations? I am sure I could do this myself with a loop, but I would prefer to learn the Rusty way.
I've run into this type of problem with an iterator of Result
s so commonly that I added a (private) helper type to the standard library called ResultShunt
. This powers the implementation of Sum
and Product
for Result
s.
I also submitted it to itertools so it can be reused:
use itertools; // 0.10.1
fn main() {
let iter_source: Vec<Result<(i32, i32), bool>> = vec![Ok((1, 2)), Err(false), Ok((3, 4))];
let z = itertools::process_results(iter_source, |iter| iter.unzip::<_, _, Vec<_>, Vec<_>>());
println!("{:?}", z);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With