我的问题的以下简化/抽象版本:
fn main() {
let foo_selectors = vec![0, 1];
let foos: Vec<_> = foo_selectors
.into_iter()
.flat_map(|i| get_foo(i).into_iter())
.collect();
println!("{:?}", foos);
}
fn get_foo(i: u8) -> [u8; 3] {
if i % 2 == 0 {
[1, 2, 3]
} else {
[4, 5, 6]
}
}
我收到以下错误消息:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:6:44
|
6 | .flat_map(|i| get_foo(i).into_iter())
| ---------- ^ temporary value dropped here while still borrowed
| |
| temporary value created here
...
10 | }
| - temporary value needs to live until here
错误消息提示借用,但我到处都使用了 into_iter
,据我所知,它拥有迭代值的所有权。我想获取从 get_foo
返回的值的所有权,并将它们的元素插入到 foos
中。我该怎么做?
最佳答案
How to take ownership of a value in flat_map
这里的flat_map
没有什么特别之处。当调用 get_foo
时,返回值的所有权转移给调用者,就像 Rust 中的其他任何地方一样。
I've used into_iter everywhere, which as I understand it, takes ownership of the iterated values.
通常,是的,但不是数组。请参阅下面的链接问题了解原因。这就是问题的根源。 flat_map
闭包拥有 get_foo
的结果,然后您引用它。引用不能在闭包之后继续存在,但这正是您要求它做的。
作为解决方法,您可以从您的函数返回一个 Vec
:
fn get_foo(i: u8) -> Vec<u8> {
if i % 2 == 0 {
vec![1, 2, 3]
} else {
vec![4, 5, 6]
}
}
您还可以在 flat_map
调用中将返回的数组转换为 Vec
。
如果您觉得情况需要,您可以实现自己的迭代器:
struct CloneArrayIter<T> {
arr: [T; 3],
idx: usize,
}
impl<T> CloneArrayIter<T> {
fn new(arr: [T; 3]) -> Self {
Self { arr, idx: 0 }
}
}
impl<T> Iterator for CloneArrayIter<T>
where
T: Clone,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.idx < 3 {
let value = self.arr[self.idx].clone();
self.idx += 1;
Some(value)
} else {
None
}
}
}
并将其用作 .flat_map(|i| CloneArrayIter::new(get_foo(i)))
我可能只使用来自 arrayvec 的 ArrayVec
虽然:
extern crate arrayvec;
use arrayvec::ArrayVec;
fn main() {
let foo_selectors = vec![0, 1];
let foos: Vec<_> = foo_selectors
.into_iter()
.flat_map(|i| get_foo(i))
.collect();
println!("{:?}", foos);
}
fn get_foo(i: u8) -> ArrayVec<[u8; 3]> {
if i % 2 == 0 { [1, 2, 3] } else { [4, 5, 6] }.into()
}
另见:
关于iterator - 如何在 flat_map 中取得一个值的所有权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45904760/