2016-01-26 8 views
14

Ich versuche, eine Nachrichten-Routing-App zu entwickeln. Ich habe die offiziellen Rust-Dokumente und einige Artikel gelesen und dachte, dass ich weiß, wie es funktioniert, Dinge zu besitzen, zu besitzen und Dinge zu leihen, aber mir wurde klar, dass ich es nicht getan habe.Kann nicht unveränderlich ausgeliehenen Inhalt als veränderbar

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 
    } 

} 

(Auch auf der playground)

Erzeugt den Fehler:

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 

Könnten Sie bitte den Fehler erklären und es wäre toll, wenn Sie mir die richtige Umsetzung geben kann.

Antwort

23

Hier eine kleinere Reproduktion des Problems ist:

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() {} 

Viele Male, wenn so etwas wie diese überraschend scheint, ist es sinnvoll zu print out the types involved. Lassen Sie sich die Art von queue ausdrucken:

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

Wir haben einen wandelbar Verweis auf einen unveränderlichen Verweis auf ein Vec<u8>. Da wir einen unveränderlichen Verweis auf die Vec haben, können wir sie nicht ändern! Wenn Sie self.data.get in self.data.get_mut ändern, wird der Typ in &mut &mut collections::vec::Vec<u8> geändert und der Code kompiliert.


Wenn Sie das Konzept der „einfügen oder aktualisieren“ implementieren möchten, sollten Sie die entry API überprüfen in, die effizienter und prägnant ist.

Darüber hinaus verwendet Rust snake_case für Methodenname, nicht camelCase.

+0

Danke. Jetzt verstehe ich es besser. Danke für den Hinweis zu den Drucktypen, es erweist sich als sehr hilfreich für die Fehlerbehebung – dmgcodevil

+0

Ist der Link unter * die beteiligten Typen ausdrucken * noch verfügbar? Es gibt eine SO-Frage, aber ich dachte, der Link deutete auf eine Antwort hin. – stej

+1

@stej der Link ist auf die Frage. Dies ermöglicht eine bessere Antwort oder eine andere Antwort für den Implementierer, wenn die Situation anders ist. In diesem Fall habe ich die Version "dem leeren Tupel zuweisen" verwendet. – Shepmaster

Verwandte Themen