我有一个函数,它操作的是一个 Vec<T>
,其目的是使用现有项的引用生成新项并将其添加到向量中。 我正在尝试使用 rayon
并行运行新数据的生成。
这是一个最简示例:
use itertools::Itertools;
use rayon::prelude::*;
fn main() {
let mut foo = Foo {
data: (0..1000).into_iter().collect(),
};
foo.run();
}
struct Foo<T> {
data: Vec<T>,
}
type Pair<'a, T> = (&'a T, &'a T);
impl<'a, T: Clone + 'a> Foo<T>
where
Vec<Pair<'a, T>>: IntoParallelIterator<Item = Pair<'a, T>>,
[T; 2]: IntoParallelIterator,
Vec<T>: FromParallelIterator<<[T; 2] as IntoParallelIterator>::Item>,
{
fn run(&'a mut self) {
let combinations: Vec<Pair<'a, T>> = self
.data
.iter()
.combinations(2)
.map(|x| (x[0], x[1]))
.collect();
let mut new_combinations: Vec<T> = combinations
.into_par_iter()
.flat_map(|(a, b)| bar(a, b))
.collect();
self.data.append(&mut new_combinations);
}
}
fn bar<T: Clone>(a: &T, b: &T) -> [T; 2] {
[a.clone(), b.clone()]
}
您可以在这里找到 Playground 的链接。
构建上面的示例会引发此错误:
error[E0502]: cannot borrow `self.data` as mutable because it is also borrowed as immutable
--> src/main.rs:36:9
|
17 | impl<'a, T: Clone + 'a> Foo<T>
| -- lifetime `'a` defined here
...
24 | let combinations: Vec<Pair<'a, T>> = self
| ___________________________----------------___-
| | |
| | type annotation requires that `self.data` is borrowed for `'a`
25 | | .data
26 | | .iter()
| |___________________- immutable borrow occurs here
...
36 | self.data.append(&mut new_combinations);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
据我所知,因为我正在收集到一个
let new_combinations: Vec<T>
中,所以对于 self.data
,不应该有不可变的引用,并且理论上应该能够借用它以可变地附加新的组合。但是,似乎self.data
被借用了具有超出此方法范围的生命周期'a
。我找不到避免指定生命周期fn run(&'a mut self)
的方法,因为我需要指定对self.data
项的引用的生命周期不能比创建组合时self
的生命周期更长。有没有一种方法可以使该方法按预期运行,即:1)选择指向
self.data
项的引用列表,2)并行应用创建新项T
的函数,最后3)使用新项更新self.data
。请注意,作为解决方法,可以将
new_combinations
从该方法返回,并单独将其附加到self.data
中。如果能够仅使用迭代器直接操作,而尽可能避免使用
collect()
,那就太好了。
0..1000
是一个迭代器,你不需要使用.into_iter()
。请参见 playground。 - jthulhubar()
克隆它们;生命周期只是被错误地注释了。 - Finomnis