2016-01-12 8 views
5

Mam funkcję, która wygląda tak:Modyfikowanie `iter` łańcuch użycie` and_then` itp

type Attributes = HashMap<String, json::Json>; 
type Store = Arc<RwLock<HashMap<String, RwLock<Attributes>>>>; 

fn get(store: &Store, key: &str) -> Option<Attributes> { 
    store.read().iter() 
     .filter_map(|g| (*g).get(key)) 
     .filter_map(|v| v.read().ok()) 
     .map(|v| (*v).clone()) 
     .next() 
} 

To kompiluje i działa dobrze. Jednak dla własnego zbudowania, I zostały próbuje zmodyfikować, aby używać standardowych Result/Option metod (bez konwersji LockResult do Iter), coś takiego:

store.read().ok() 
    .and_then(|g| (*g).get(key)) 
    .and_then(|v| v.read().ok()) 
    .map(|v| (*v).clone()); 

Ale to mówi mi, że g does not live long enough. Próbowałem dodawać ref i as_ref w różnych miejscach, ale nie mogę go skompilować. czego mi brakuje?

wiem, że mogę zmusić go do pracy jak:

store.read().ok() 
     .and_then(|g| { 
      (*g).get(key) 
       .and_then(|v| v.read().ok()) 
       .map(|v| (*v).clone()) 
     }) 

Ale chciałbym, aby móc łańcucha nim jak w przypadku iter.

+0

(Potencjalnie noob pytanie) Czy to nie jest różnica między 'iter()' i 'into_iter()'? Możesz użyć 'do_iter()', aby przenieść własność na resztę łańcucha, tak aby twoje referencje żyły w całym tekście? –

+0

@ SimonWhitehead, dzięki za komentarz! Tak, myślę, że to jest dokładnie różnica między 'iter' i' into_iter' - ale w odwrotnej kolejności. Ja ** chcę używać 'iter' zamiast' into_iter', a właściwie chcę wariantu 'and_then', który robi coś takiego jak' iter', ale nie mogę znaleźć odpowiedniego kombinacja 'as_ref' itp., który to robi. Kiedy zmieniam pierwszy przykład powyżej, aby użyć 'into_iter', otrzymuję te same komunikaty o błędach, co mój drugi przykład. –

+0

Nie przypuszczam, że moglibyście połączyć MVCE w kojec dla mnie/innych, aby mogli się nimi zajmować? –

Odpowiedz

3

OK, kompilator naprawdę się ze mną dogaduje dziś wieczorem.

Mam ten zaklęcie do kompilacji:

fn get(store: &Store, key: &str) -> Option<Attributes> { 
    let r = store.read(); 
    let x = r.as_ref().ok() 
     .and_then(|g| (*g).get(key)) 
     .and_then(|v| v.read().ok()) 
     .map(|v| (*v).clone()); 
    x 
} 

Jeśli inline albo r lub x, dostaniesz kolejny does not live long enough błąd ponownie. Nie jestem pewien dlaczego, ponieważ w zasadzie strażnik powinien pozostać aktywny jako tymczasowy do końca wyciągu.

Powiązane problemy