我想做什么:
enum Test {
Value1,
Value2,
Value3
}
fn main() {
let mut test_vec: Vec<Test> = Vec::new();
test_vec.push(Test::Value2);
if let Some(last) = test_vec.last() {
test_vec.push(*last);
}
//Wanted output: vector with [Test::Value2, Test::Value2]
}
我了解当我致电last()
时,它会返回Option<&Test>
所以它将借用test_vec
直到if-let块结束。
我尝试了以下但没有成功:
if let Some(last) = test_vec.last().map(|v| v.clone()) {
test_vec.push(*last);
}
//and
let last = test_vec.last().unwrap().clone();
test_vec.push(*last);
答案 0 :(得分:6)
要解决借阅问题,您可以拨打Option::cloned
,从Option<T>
生成Option<&T>
。为此,Test
必须实施Clone
。您可以使用Clone
:
Test
实施derive
// To allow assert_eq, we also derive Debug and PartialEq
#[derive(Debug, PartialEq, Clone)]
enum Test {
Value1,
Value2,
Value3
}
fn main() {
let mut test_vec = Vec::new();
test_vec.push(Test::Value2);
if let Some(last) = test_vec.last().cloned() {
test_vec.push(last);
}
assert_eq!(vec![Test::Value2, Test::Value2], test_vec);
}
答案 1 :(得分:3)
当试图找出借用检查者为什么抱怨时,识别所涉及的类型会很有用。
如果您输入:
let _: () = test_vec.last().map(|v| v.clone());
您收到的错误是抱怨()
和core::option::Option<&Test>
类型不同。
发生了什么?非常简单地说,如果您克隆&Test
,则会得到&Test
,因此在.map(|v| v.clone())
上调用Option<&Test>
会得到Option<&Test>
。显然,它仍然借用。
如果您输入以下内容,下次尝试时会出现同样的问题:
let _: () = test_vec.last().unwrap().clone();
您收到的错误是抱怨()
和&Test
类型不同。
通过unwrap
调用Option<&Test>
,您会获得一个&Test
,然后将其克隆到&Test
。
所以,问题是缺少解除引用。您需要提前取消引用,以避免在test_vec
中借用Some(last)
:
if let Some(last) = test_vec.last().map(|v| (*v).clone()) {
test_vec.push(last);
}
当然,这不起作用,因为Test
没有实现clone
。一旦修复(由#[derive(Clone)]
),它就会编译。
由于从引用中克隆是如此常见的需求,Option
(和Iterator
)上有一个名为cloned
的专用方法:
if let Some(last) = test_vec.last().cloned() {
test_vec.push(last);
}