การซิปเวกเตอร์ประเภทเดียวกันทำให้เกิดประเภทต่างๆภายในการปิดแผนที่

Aug 16 2020

พื้นหลัง

ระบุประเภทตัวแปร enum (ไม่สามารถคัดลอกได้):

enum AstNode {
  Op(Func, Box<AstNode>, Box<AstNode>),
  Val(f64),
  // others...
}

พยายามเรียกใช้การดำเนินการกับเวกเตอร์สองตัวดังกล่าว:

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!
}

ภายในปิดที่lhsองค์ประกอบถือว่าชนิดl: &AstNodeในขณะที่ซิปองค์ประกอบใช้ประเภทrhs l: AstNode(สังเกตการประกาศที่แตกต่างกันใน tuple การปิด)

คำถาม

เหตุใดจึงเป็นเช่นนี้

มีวิธีการวนซ้ำองค์ประกอบของเวกเตอร์ตามค่าแทนการอ้างอิงหรือไม่? ดูเหมือนจะเป็นไปได้จากพฤติกรรมที่สังเกตได้ขององค์ประกอบซิป

(ในตัวอย่างนี้ความแตกต่างนี้ส่งผลให้เกิดความแปลกเล็กน้อยในการประกาศไวยากรณ์ แต่ในทางปฏิบัติฉันได้ต่อต้านตัวตรวจสอบการยืมเมื่อส่งผ่านตัวแปรอ้างอิงไปยังฟังก์ชัน)

คำเตือน: ฉันค่อนข้างใหม่กับ Rust

คำตอบ

6 kmdreko Aug 16 2020 at 04:55

Iterator::zipวิธีการที่ไม่ได้ทำอะไรพิเศษก็เป็นเพียงการรวมทั้ง iterators คุณพบว่าlhs.iter()ผลตอบแทนIterator<&AstNode>while rhsให้ผลIterator<AstNode>( &vs non- &)

มีวิธีการวนซ้ำองค์ประกอบของเวกเตอร์ตามค่าแทนการอ้างอิงหรือไม่? ดูเหมือนจะเป็นไปได้จากพฤติกรรมที่สังเกตได้ขององค์ประกอบซิป

ใช่มีวิธีควบคุมพฤติกรรมนี้ กุญแจสำคัญคือการสังเกตว่าzip()อาร์กิวเมนต์rhsต้องใช้IntoIteratorลักษณะ ในทางโต้ตอบzip()จะเรียกrhs.into_iter()เพื่อรับตัววนซ้ำจากมัน พฤติกรรมทั่วไปคือ.iter()เพียงยืมแหล่งที่มาดังนั้นจึงสามารถให้การอ้างอิงถึงค่าของมันเท่านั้น ในขณะที่บริโภคหรือ"เป็นเจ้าของ"แหล่งที่มาและสามารถให้มูลค่าที่เป็นเจ้าของได้.into_iter()

รวมเหล่านั้นที่คุณสามารถทำได้lhs.into_iter().zip(rhs)เพื่อให้ได้ iterator กว่าค่า(AstNode, AstNode)หรือการใช้งานlhs.iter().zip(rhs.iter())ที่จะได้รับมากกว่า iterator (&AstNode, &AstNode)อ้างอิง