Aynı türden sıkıştırma vektörleri, harita kapanışında farklı türlerle sonuçlanır

Aug 16 2020

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, lhselemanlar tip l: &AstNodealırken, fermuarlı rhselemanlar 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

6 kmdreko Aug 16 2020 at 04:55

Iterator::zipYöntem şey special yapıyor, sadece her iki yineleyicinızı birleştirerek değildir. lhs.iter()Bir Iterator<&AstNode>süre rhssonucunun 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 rhsuygulamak 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).