2017-03-06 5 views
2

Ich versuche eine Lookup-Funktion zu implementieren, die einen veränderbaren Verweis auf einen Wert zurückgibt, der im self-Wert enthalten ist. Da der zurückgegebene Verweis auf Daten verweist, die außerhalb der lookup-Funktion (self.verts) liegen, sieht der Borrow-Checker normalerweise kein Problem damit. In meinem Fall filtere ich jedoch self.verts, bevor ich den Verweis zurückgebe und ihn an einen neuen, eigenen Namen binde. Wenn ich versuche, einen Wert aus diesem Ort im Besitz Array zurück erhalte ich die Fehler Kompilierung:So beschwichtigen Sie den Border Checker, wenn Sie den Verweis auf den gefilterten Vektor externer Referenzen zurückgeben

error: `vs` does not live long enough 
    --> src/util/graph.rs:18:37 
    | 
18 |   if vs.len() > 0 { Some(&mut vs[0]) } else { None } 
    |          ^^ does not live long enough 
19 |  } 
    |  - borrowed value only lives until here 
    | 
note: borrowed value must be valid for the lifetime 'a as defined on the body at 16:75... 
    --> src/util/graph.rs:16:76 
    | 
16 |  pub fn lookup_id<'a>(&'a mut self, id: &str) -> Option<&'a mut Vertex> { 
    | ____________________________________________________________________________^ starting here... 
17 | |   let vs:Vec<&mut Vertex> = self.verts.iter_mut().filter(|x| x.id == id).collect(); 
18 | |   if vs.len() > 0 { Some(&mut vs[0]) } else { None } 
19 | |  } 
    | |_____^ ...ending here 

Ich verstehe, dass ich nicht einen Verweis auf lokalen Besitz Inhalt zurückgeben kann, und ich vermute, das ist, wie der Compiler meinen Code interpretieren, aber das möchte ich nicht machen. Was Sie tun möchten, ist eine Referenz auf einen Wert im Vektor self.verts zurückzugeben, so dass die zurückgegebene Referenz die gleiche Lebensdauer und die Struktur hat, an der die Suche ausgeführt wird. Hier ist mein aktueller Versuch:

pub fn lookup_id<'a>(&'a mut self, id: &str) -> Option<&'a mut Vertex> { 
    let vs:Vec<&'a mut Vertex> = self.verts.iter_mut().filter(|x| x.id == id).collect(); 
    if vs.len() > 0 { Some(&mut vs[0]) } else { None } 
} 

Dieser Code kompiliert nicht, weil vs does not live long enough. Wie sage ich dem Compiler, dass ein Verweis in vs und nicht ein Verweis auf vs zurückgegeben werden soll?

Antwort

2

Sie kehren zurück &mut &mut Vertex.

Wenn Sie den Rest der Elemente sind zu verwerfen, können Sie faul Berechnung tun: self.verts.iter_mut().filter(|x| x.id == id).next()

0

ich so etwas wie &mut &mut Vertex vermutet. Leider gab es ohne die &mut vor der vs mehrere andere Compilerfehler. Wie sich herausstellt, gibt Rust beim Indexieren Referenzen zurück, etwas, das ich nicht kannte. Ich musste das std::vec Modul überprüfen und ich fand, dass remove() den Wert direkt zurückgibt. Dieser Code funktioniert:

pub fn lookup_id(&mut self, id: &str) -> Option<&mut Vertex> { 
    let mut vs:Vec<&mut Vertex> = self.verts.iter_mut().filter(|x| x.id == id).collect(); 
    if vs.len() > 0 { Some(vs.remove(0)) } else { None } 
} 

Diese Version ist aber viel sauberer:

pub fn lookup_id(&self, id: &str) -> Option<&Vertex> { 
    self.verts.iter().find(|x| x.id == id) 
} 
Verwandte Themen