2016-06-01 3 views
2

私は何をしようとしている同じベクトルにそれをプッシュする:私はlast()を呼び出すときに、それが返されることを理解しベクトルの最後の要素を取得し、

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] 
} 

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); 

答えて

2

ボローチェッカーは関係する種類を識別するのに役立ちます不平を言う理由を把握しようとしています。

あなたが出て入力した場合:

let _:() = test_vec.last().map(|v| v.clone()); 

あなたは()core::option::Option<&Test>が同じ型ではないことを訴えてエラーが発生します。

何が起こっているのですか?非常に単純に言えば、&Testをクローンした場合、&Testが得られ、Option<&Test>.map(|v| v.clone())を呼び出すと、Option<&Test>となります。明らかに、それはまだ借りる。

あなたが出て入力した場合、同じ問題が、あなたの次の試行で発生します。

let _:() = test_vec.last().unwrap().clone(); 

あなたは()&Testが同じ型ではないことを訴えてエラーが発生します。

Option<&Test>unwrapを呼び出すと、&Testが得られ、&Testにクローニングされます。


ので、問題はを逆参照の欠如です。あなたはSome(last)で借入test_vecを避けるために、以前の間接参照する必要があります。

もちろんの
if let Some(last) = test_vec.last().map(|v| (*v).clone()) { 
    test_vec.push(last); 
} 

Testcloneを実装していないので、これは動作しません。これが固定されると(#[derive(Clone)]によって)、コンパイルされます。

参照からのクローニングは、そのような一般的な必要性であるので、Option(及びIterator)に専用の方法があるcloned呼ば:

if let Some(last) = test_vec.last().cloned() { 
    test_vec.push(last); 
} 
5

Option<&T>からOption<T>を生成し、あなたがOption::clonedを呼び出すことができボローの問題を、解決するために。これを行うには、TestCloneを実装する必要があります。あなたはderiveを使用してTestためCloneを実装できます。

// 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); 
} 
関連する問題