Molte librerie consentono di definire un tipo che implementa un dato trait
da utilizzare come gestore di richiamata. Ciò richiede di raggruppare tutti i dati necessari per gestire l'evento insieme in un singolo tipo di dati, il che complica i prestiti.Qual è il modo più rapido e idiomatico di mutare più campi della struttura contemporaneamente?
Ad esempio, mio
consente di implementare Handler
e fornire la struttura quando si run the EventLoop
. Si consideri un esempio con questi tipi di dati banalizzati:
struct A {
pub b: Option<B>
};
struct B;
struct MyHandlerType {
pub map: BTreeMap<Token, A>,
pub pool: Pool<B>
}
vostro gestore ha una mappa da Token
a elementi di tipo A
. Ogni articolo di tipo A
può o non può avere già un valore associato di tipo B
. Nel gestore, si desidera cercare il valore A
per un dato Token
e, se non ha già un valore B
, ottenerne uno tra del gestore.
impl Handler for MyHandlerType {
fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>,
token: Token, events: EventSet) {
let a : &mut A = self.map.get_mut(token).unwrap();
let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
// Continue working with `a` and `b`
// ...
}
}
In questo accordo, anche se è intuitivo possibile vedere che self.map
e self.pool
sono entità distinte, il correttore prestito lamenta che self
è già preso in prestito (via self.map
) quando andiamo per accedere self.pool
.
Un possibile approccio a questo sarebbe quello di avvolgere ogni campo in MyHandlerType
in Option<>
. Poi, all'inizio della chiamata al metodo, take()
quei valori su self
e ripristinarli al termine della chiamata:
struct MyHandlerType {
// Wrap these fields in `Option`
pub map: Option<BTreeMap<Token, A>>,
pub pool: Option<Pool<B>>
}
// ...
fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>,
token: Token, events: EventSet) {
// Move these values out of `self`
let map = self.map.take().unwrap();
let pool = self.pool.take().unwrap();
let a : &mut A = self.map.get_mut(token).unwrap();
let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
// Continue working with `a` and `b`
// ...
// Restore these values to `self`
self.map = Some(map);
self.pool = Some(pool);
}
Questo funziona si sente, ma un po 'Kluge-y. Introduce inoltre il sovraccarico dei valori di spostamento all'interno e all'esterno di self
per ciascuna chiamata di metodo.
Qual è il modo migliore per farlo?
!!! Grazie! Sapevo di destrutturare, ma non avevo idea che potessi usarlo per ottenere riferimenti simultanei mutabili. Questo è stato un grande aiuto! – zslayton