2016-01-12 7 views
5

Ho una funzione che assomiglia:Modifica di `iter` catena per usare` and_then`, ecc

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

Questo compila e funziona bene. Tuttavia, per la mia edificazione, ho cercato di modificare il presente per uso standard Result/Option metodi (senza convertire l'LockResult a un Iter), qualcosa come:

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

Ma questo mi dice che g does not live long enough. Ho provato ad aggiungere ref e as_ref in vari punti, ma non riesco a farlo compilare. Cosa mi manca?

so che posso farlo funzionare come:

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

ma vorrei essere in grado di catena di essa come nel caso iter.

+0

(Domanda potenzialmente noob) Non è questa la differenza tra 'iter()' e 'in_iter()'? Potresti voler usare 'into_iter()' per spostare la proprietà sul resto della catena in modo che i tuoi riferimenti vengano visualizzati in modo permanente? –

+0

@SimonWhitehead, grazie per il commento! Sì, penso che questa sia esattamente la differenza tra 'iter' e' into_iter' - ma al contrario. Io ** voglio ** usare 'iter' piuttosto che' into_iter', e infatti voglio una variante 'and_then' che faccia qualcosa come' iter', ma non riesco a capire la combinazione giusta di 'as_ref' , ecc., fa questo. Quando cambio il primo esempio sopra per usare 'into_iter', ottengo gli stessi messaggi di errore del mio secondo esempio. –

+0

Non credo che potresti mettere insieme un MVCE sul box per me/gli altri con cui armeggiare? –

risposta

3

OK, il compilatore mi sta davvero scherzando stasera.

ho avuto questa formula magica per la compilazione:

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 
} 

Se in linea sia r o x, si otterrà di nuovo un altro errore does not live long enough. Non sono sicuro del perché, poiché in linea di principio, la guardia di blocco dovrebbe rimanere attiva come temporanea fino alla fine della dichiarazione.

Problemi correlati