2016-01-26 6 views
14

私はメッセージルーティングアプリケーションを開発しようとしています。私は公式のRustドキュメントといくつかの記事を読んだことがあります。ポインタ、所有、借用の仕組みがわかりましたが、私はそうではないことに気付きました。不変の借用したコンテンツを変更可能なものとして借りることはできません

use std::collections::HashMap; 
use std::vec::Vec; 

struct Component { 
    address: &'static str, 
    available_workers: i32, 
    lang: i32 
} 

struct Components { 
    data: HashMap<i32, Vec<Component>> 
} 

impl Components { 
    fn new() -> Components { 
     Components {data: HashMap::new() } 
    } 

    fn addOrUpdate(&mut self, component: Component) -> &Components { 
     if !self.data.contains_key(&component.lang) { 

      self.data.insert(component.lang, vec![component]); 
     } else { 
      let mut q = self.data.get(&component.lang); // this extra line is required because of the error: borrowed value does not live long enough 
      let mut queue = q.as_mut().unwrap(); 
      queue.remove(0); 
      queue.push(component); 
     } 
     self 
    } 

} 

playgroundでも利用可能)エラーが発生します。

error: cannot borrow immutable borrowed content `**queue` as mutable 
    --> src/main.rs:26:13 
    | 
26 |    queue.remove(0); 
    |    ^^^^^ cannot borrow as mutable 

error: cannot borrow immutable borrowed content `**queue` as mutable 
    --> src/main.rs:27:13 
    | 
27 |    queue.push(component); 
    |    ^^^^^ cannot borrow as mutable 

あなたはエラーを説明してもらえますし、あなたが私の右の実装を与えることができればそれは素晴らしいことです。

答えて

23

はここにあなたの問題の少ない再現です:

use std::collections::HashMap; 

struct Components { 
    data: HashMap<u8, Vec<u8>> 
} 

impl Components { 
    fn add_or_update(&mut self, component: u8) { 
     let mut q = self.data.get(&component); 
     let mut queue = q.as_mut().unwrap(); 
     queue.remove(0); 
    } 
} 

fn main() {} 

何度も、何かがこのような驚くべきだが、それはprint out the types involvedに便利です。さんはqueueの種類をプリントアウトしてみましょう:

let mut q:() = self.data.get(&component); 
= note: expected type `()` 
      found type `&mut &std::vec::Vec<u8>` 

我々はVec<u8>から不変参照へ可変の参照を持っています。 Vecへの不変な参照があるため、修正することはできません! self.data.getself.data.get_mutに変更すると、タイプが&mut &mut collections::vec::Vec<u8>に変更され、コードがコンパイルされます。


あなたが「INSERTまたはUPDATE」の概念を実装したい場合は、より効率的かつ簡潔である、entry APIにチェックする必要があります。

それ以外では、RustはcamelCaseではなく、メソッド命名にsnake_caseを使用します。

+0

ありがとうございました。今私はそれをよく理解しています。印刷タイプに関するアドバイスをお寄せいただきありがとうございます。それはトラブルシューティングのために非常に役立ちます。 – dmgcodevil

+0

関連するタイプを印刷しますか*まだ利用できますか? SOの質問がありますが、私はそのリンクが何らかの答えを指摘していると思いました。 – stej

+1

@stejのリンクは質問です。そうすれば、より良い答えが得られます。あるいは、状況が異なる場合、実装者が別の答えを選ぶことができます。この場合、私は "空タプルに割り当てる"バージョンを使用しました。 – Shepmaster

関連する問題