Sto provando a codificare un elenco generico come esercizio - so che è già supportato dalla sintassi, sto solo cercando di capire se posso codificare una struttura dati ricorsiva. A quanto pare, non posso. Sto colpendo un muro quando voglio accedere a più di un campo di un valore di struct di proprietà.Come associare più campi struct senza ottenere l'errore "usa valore spostato"?
Quello che sto facendo è fondamentalmente questo - mi definisco una struct che conterrà un elenco:
struct ListNode<T> {
val: T,
tail: List<T>
}
struct List<T>(Option<Box<ListNode<T>>>);
Lista vuota è solo rappresentata da List(None)
.
Ora, voglio essere in grado di aggiungere a un elenco:
impl<T> List<T> {
fn append(self, val: T) -> List<T> {
match self {
List(None) => List(Some(Box::new(ListNode { val: val, tail: List(None) }))),
List(Some(node)) => List(Some(Box::new(ListNode { val: node.val, tail: node.tail.append(val) })))
}
}
}
Ok, in modo tale che non riesce con un errore "usato valore mosso: nodo" alla node.tail con una spiegazione che si trattava spostato a "node.val". Questo è comprensibile.
Così, ho cercare modi per utilizzare più di un campo di una struct e ho trovato questo: Avoiding partially moved values error when consuming a struct with multiple fields
Grande, così lo farò:
List(Some(node)) => {
let ListNode { val: nval, tail: ntail } = *node;
List(Some(Box::new(ListNode { val: nval, tail: ntail.append(val) })))
}
Beh, no, il nodo ancora viene spostato all'assegnazione ("errore: uso del valore spostato" nodo "" a "coda: ntail"). Apparentemente questo non funziona più come nel link.
ho provato anche con arbitri:
List(Some(node)) => {
let ListNode { val: ref nval, tail: ref ntail } = *node;
List(Some(Box::new(ListNode { val: *nval, tail: (*ntail).append(val) })))
}
Questa volta la decostruzione passa, ma la creazione del nuovo nodo viene a mancare con "l'errore: non può uscire di contenuti in prestito".
Mi manca qualcosa di ovvio qui? In caso contrario, qual è il modo corretto per accedere a più campi di una struttura che non viene passata per riferimento?
Grazie in anticipo per qualsiasi aiuto!
EDIT: Oh, dovrei probabilmente aggiungere che sto usando Rust 1.1 stabile.
Grazie! Questo funziona davvero :) Perché Box funziona in questo modo, però? C'è una spiegazione ragionevole? – ebvalaim
Sono abbastanza sicuro che abbia a che fare con il fatto che l'unboxing deref è un po 'magico per il compilatore. –
ecco il bug corrispondente: https://github.com/rust-lang/rust/issues/16223 –