Aynı türden sıkıştırma vektörleri, harita kapanışında farklı türlerle sonuçlanır
Arka fon
Bir enum varyant türü verildiğinde (kopyalanamaz):
enum AstNode {
Op(Func, Box<AstNode>, Box<AstNode>),
Val(f64),
// others...
}
Bu tür iki vektör üzerinde bir işlem gerçekleştirmeye çalışmak:
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!
}
Kapağın içinde, lhs
elemanlar tip l: &AstNode
alırken, fermuarlı rhs
elemanlar tip alır l: AstNode
. (Kapanış dizisindeki farklı bildirimlere dikkat edin).
Sorular
Durum neden böyle?
Bir vektörün öğelerini referans yerine değere göre yinelemenin bir yolu var mı? Bu, sıkıştırılmış öğelerin gözlemlenen davranışından mümkün görünüyor.
(Bu örnekte, bu fark sözdizimi bildiriminde hafif bir tuhaflığa neden olur, ancak pratikte, referans değişkenini bir işleve geçirirken ödünç denetleyiciye çarptım)
Sorumluluk reddi: Rust'ta oldukça yeniyim
Yanıtlar
Iterator::zipYöntem şey special yapıyor, sadece her iki yineleyicinızı birleştirerek değildir. lhs.iter()
Bir Iterator<&AstNode>
süre rhs
sonucunun bir Iterator<AstNode>
(yerine &
olmayan &
) verdiğini görüyorsunuz .
Bir vektörün öğelerini referans yerine değere göre yinelemenin bir yolu var mı? Bu, sıkıştırılmış öğelerin gözlemlenen davranışından mümkün görünüyor.
Evet, bu davranışı kontrol etmenin bir yolu var. Anahtar, zip()
argümanın özelliği rhs
uygulamak zorunda olduğunu fark etmektir IntoIterator
. Interally, ondan bir yineleyici almak için zip()
arayacak rhs.into_iter()
. Geleneksel davranış, .iter()yalnızca kaynağı ödünç almak ve bu nedenle yalnızca değerlerine referanslar sağlamaktır. İken tüketir veya "sahiplenir" kaynağı ve sahip olunan değerleri verebilir..into_iter()
Bunları birleştirerek, lhs.into_iter().zip(rhs)
değerlerin üzerinde bir yineleyici elde etmek için yapabilir (AstNode, AstNode)
veya lhs.iter().zip(rhs.iter())
referanslar üzerinden bir yineleyici elde etmek için kullanabilirsiniz (&AstNode, &AstNode)
.