Kompresowanie wektorów tego samego typu skutkuje różnymi typami w zamknięciu mapy
tło
Biorąc pod uwagę typ wariantu wyliczenia (nie do skopiowania):
enum AstNode {
Op(Func, Box<AstNode>, Box<AstNode>),
Val(f64),
// others...
}
Próba uruchomienia operacji na dwóch takich wektorach:
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!
}
W zamknięciu lhs
elementy przyjmują typ, l: &AstNode
a rhs
elementy zapinane na zamek l: AstNode
. (Zwróć uwagę na różne deklaracje w krotce zamknięcia).
pytania
Dlaczego tak się dzieje?
Czy istnieje sposób na iterację elementów wektora według wartości zamiast referencji? Wydawałoby się, że jest to możliwe na podstawie obserwowanego zachowania zapinanych elementów.
(W tym przykładzie ta różnica powoduje niewielką dziwność w deklaracji składni, ale w praktyce trafiłem na narzędzie sprawdzania pożyczki podczas przekazywania zmiennej referencyjnej do funkcji)
Zastrzeżenie: Jestem całkiem nowy w Rust
Odpowiedzi
Iterator::zipMetoda nie robi nic szczególnego, to jest po prostu połączenie obu iteratory. Odkrywasz, że lhs.iter()
daje Iterator<&AstNode>
chwilę, rhs
daje Iterator<AstNode>
( &
vs nie &
).
Czy istnieje sposób na iterację elementów wektora według wartości zamiast referencji? Wydawałoby się, że jest to możliwe na podstawie obserwowanego zachowania zapinanych elementów.
Tak, istnieje sposób na kontrolowanie tego zachowania. Kluczem jest zauważenie, że zip()
argument ten rhs
musi implementować IntoIterator
cechę. Interally, zip()
wywoła, rhs.into_iter()
aby uzyskać z niego iterator. Konwencjonalne zachowanie polega na tym, że .iter()tylko pożycza źródło i dlatego może podawać tylko odniesienia do jego wartości. Podczas gdy konsumuje lub „przejmuje na własność” źródło i może przynosić posiadane wartości..into_iter()
Łącząc je, możesz lhs.into_iter().zip(rhs)
uzyskać iterator dla wartości (AstNode, AstNode)
lub użyć go, lhs.iter().zip(rhs.iter())
aby uzyskać iterator dla odwołań (&AstNode, &AstNode)
.