La compressione di vettori dello stesso tipo produce tipi diversi all'interno della chiusura della mappa
sfondo
Dato un tipo di variante enum (non copiabile):
enum AstNode {
Op(Func, Box<AstNode>, Box<AstNode>),
Val(f64),
// others...
}
Tentativo di eseguire un'operazione su due di questi vettori:
fn apply_func_iterative(func: Func, lhs: Vec<AstNode>, rhs: Vec<AstNode>) -> Vec<AstNode> {
lhs.iter().zip(rhs).map(|(&l,r)| apply_func(func,l,r)).collect() // l and r are declared differently!
}
fn apply_func(func: Func, lhs: AstNode, rhs: AstNode) -> AstNode {
// magic happens here!
}
All'interno della chiusura, gli lhs
elementi assumono tipo l: &AstNode
mentre gli rhs
elementi zippati assumono tipo l: AstNode
. (Notare le diverse dichiarazioni nella tupla di chiusura).
Domande
Perché è così?
Esiste un modo per iterare gli elementi di un vettore per valore invece che per riferimento? Sembrerebbe che ciò sia possibile dal comportamento osservato degli elementi zippati.
(In questo esempio, questa differenza si traduce in una leggera stranezza nella dichiarazione della sintassi, ma in pratica, mi sono imbattuto nel controllo del prestito quando ho passato la variabile di riferimento in una funzione)
Dichiarazione di non responsabilità: sono abbastanza nuovo su Rust
Risposte
Il Iterator::zipmetodo non sta facendo nulla di speciale, sta semplicemente combinando entrambi gli iteratori. Stai scoprendo che lhs.iter()
produce un Iterator<&AstNode>
mentre rhs
produce un Iterator<AstNode>
( &
vs non- &
).
Esiste un modo per iterare gli elementi di un vettore per valore invece che per riferimento? Sembrerebbe che ciò sia possibile dal comportamento osservato degli elementi zippati.
Sì, c'è un modo per controllare questo comportamento. La chiave è notare che zip()
l'argomento di rhs
deve implementare il IntoIterator
tratto. Interamente, zip()
chiamerà rhs.into_iter()
per ottenere un iteratore da esso. Il comportamento convenzionale è che prende in prestito.iter() solo la fonte e quindi può fornire solo riferimenti ai suoi valori. Mentre consuma o "assume la proprietà" della fonte e può produrre valori di proprietà..into_iter()
Combinando questi, puoi lhs.into_iter().zip(rhs)
ottenere un iteratore sui valori (AstNode, AstNode)
o utilizzare lhs.iter().zip(rhs.iter())
per ottenere un iteratore sui riferimenti (&AstNode, &AstNode)
.