我想要做像这样的事情:
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
}
// ...
}
}
使用此代码时无法编译,会出现错误:在此上下文中必须知道该值的类型
。经过多次试验,我将其编译成功了,代码如下:
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
}
}
然而,我希望避免不必要地分配Vec<(A, B)>
。
不使用中间分配,这可行吗?我相信我可以用循环自己实现,但我更喜欢学习Rust的方法。
Vec<Result<_, _>>
时collect会做正确的事情。”这将成为一个单独的问题,幸运的是已经在这里得到了答案(https://dev59.com/kV8d5IYBdhLWcg3w21Om#26370894)。 - E net4unzip
的行为与collect
相当不同:根据 API 明确规定,unzip
将创建两个空容器,并使用extend
将数据推入它们。这意味着它无法对Result
进行特殊处理。 - E net4