2016-01-26 12 views
14

Sto provando a sviluppare un'app per il routing dei messaggi. Ho letto i documenti ufficiali di Rust e alcuni articoli e ho pensato che ho capito come funzionano i puntatori, possedere e prendere in prestito le cose, ma mi sono reso conto che non l'ho fatto.Impossibile prendere in prestito il contenuto mutuo immutabile come mutabile

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 
    } 

} 

(Disponibile anche sul playground)

genera l'errore:

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 

Potrebbe spiegare l'errore e sarebbe bello se mi potete dare il giusto implementazione.

risposta

23

Ecco una riproduzione più piccola del problema:

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

Molte volte, quando qualcosa sembra sorprendente come questo, è utile print out the types involved. Diamo stampare il tipo di queue:

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

Abbiamo un riferimento mutabile in immutabili riferimento ad un Vec<u8>. Poiché abbiamo un riferimento immutabile allo Vec, non possiamo modificarlo! La modifica da self.data.get a self.data.get_mut cambia il tipo in &mut &mut collections::vec::Vec<u8> e il codice viene compilato.


Se si desidera implementare il concetto di "inserire o aggiornare", si dovrebbe verificare nel entry API, che è più efficiente e concisa.

Oltre a ciò, Rust utilizza snake_case per la denominazione del metodo, non camelCase.

+0

Grazie. Ora capisco meglio. Grazie per i consigli sui tipi di stampa, risulta molto utile per la risoluzione dei problemi – dmgcodevil

+0

Il link sotto * stampa i tipi coinvolti * ancora disponibili? C'è una domanda su SO, ma ho pensato che il link indicasse qualche risposta. – stej

+1

@stej il collegamento è alla domanda. Ciò consente di ottenere una risposta migliore o che l'implementatore scelga una risposta diversa se la situazione è diversa. In questo caso ho usato la versione "Assegna alla tupla vuota". – Shepmaster

Problemi correlati