ฉันคิดว่ามีบางอย่างที่จะอธิบายเพิ่มเติมอีกเล็กน้อย ประเภทการเก็บเช่นVec<T>และVecDeque<T>มีinto_iterวิธีการที่อัตราผลตอบแทนเพราะพวกเขาใช้T IntoIterator<Item=T>ไม่มีอะไรที่จะหยุดเราจะสร้างประเภทคือFoo<T>ถ้าซึ่งเป็นซ้ำมากกว่าก็จะให้ผลผลิตไม่ได้แต่อีกประเภทหนึ่งT Uนั่นคือการดำเนินการFoo<T>IntoIterator<Item=U>
ในความเป็นจริงมีตัวอย่างบางส่วนstd: &Path การดำเนินการ IntoIterator<Item=&OsStr>และการดำเนินการ&UnixListener IntoIterator<Item=Result<UnixStream>>
ความแตกต่างระหว่างinto_iterและiter
กลับไปที่คำถามเดิมกับความแตกต่างระหว่างและinto_iter iterคล้ายกับคนอื่น ๆ ที่มีการชี้ความแตกต่างก็คือว่าinto_iterเป็นวิธีการที่จำเป็นของการIntoIteratorที่สามารถให้ผลผลิตชนิดใด ๆ IntoIterator::Itemที่ระบุไว้ใน โดยทั่วไปหากประเภทดำเนินIntoIterator<Item=I>ตามแบบแผนก็มีสองวิธี ad-hoc: iterและiter_mutที่ผลผลิต&Iและ&mut Iตามลำดับ
สิ่งที่มันหมายถึงคือเราสามารถสร้างฟังก์ชั่นที่ได้รับประเภทที่มีinto_iterวิธีการ (เช่นมันเป็น iterable) โดยใช้ลักษณะผูกพัน:
fn process_iterable<I: IntoIterator>(iterable: I) {
for item in iterable {
// ...
}
}
อย่างไรก็ตามเราไม่สามารถ*ใช้ลักษณะผูกพันที่จะต้องใช้ชนิดที่จะมีiterวิธีการหรือiter_mutวิธีการเพราะพวกเขากำลังเพียงการประชุม เราสามารถพูดได้ว่าinto_iterมีมากขึ้นใช้ได้อย่างกว้างขวางกว่าหรือiteriter_mut
ทางเลือกเพื่อiterและiter_mut
ที่น่าสนใจที่จะสังเกตเห็นก็คือว่าiterไม่ได้เป็นวิธีเดียวที่จะได้รับการ iterator &Tที่อัตราผลตอบแทน โดยการประชุม (อีกครั้ง) ประเภทคอลเลกชันSomeCollection<T>ในstdที่มีiterวิธีการยังมีประเภทของการอ้างอิงที่ไม่เปลี่ยนรูปของพวกเขาดำเนินการ&SomeCollection<T> IntoIterator<Item=&T>ตัวอย่างเช่น&Vec<T> การดำเนินการ IntoIterator<Item=&T>เพื่อให้เราสามารถทำซ้ำได้มากกว่า&Vec<T>:
let v = vec![1, 2];
// Below is equivalent to: `for item in v.iter() {`
for item in &v {
println!("{}", item);
}
หากv.iter()เทียบเท่ากับ&vที่ใช้กันทั้งสองIntoIterator<Item=&T>เหตุใด Rust จึงให้ทั้งสองอย่าง สำหรับการยศาสตร์ ในforลูปก็รัดกุมมากขึ้นอีกนิดกับการใช้งาน&vกว่าv.iter(); แต่ในกรณีอื่น ๆv.iter()มีความชัดเจนมากกว่า(&v).into_iter():
let v = vec![1, 2];
let a: Vec<i32> = v.iter().map(|x| x * x).collect();
// Although above and below are equivalent, above is a lot clearer than below.
let b: Vec<i32> = (&v).into_iter().map(|x| x * x).collect();
ในทำนองเดียวกันในforลูปv.iter_mut()สามารถถูกแทนที่ด้วย&mut v:
let mut v = vec![1, 2];
// Below is equivalent to: `for item in v.iter_mut() {`
for item in &mut v {
*item *= 2;
}
เมื่อใดที่จะให้ (ใช้งาน) into_iterและiterวิธีการสำหรับประเภท
หากประเภทมี "ทาง" เดียวที่จะวนซ้ำเราควรใช้ทั้งสองอย่าง อย่างไรก็ตามหากมีสองวิธีขึ้นไปสามารถทำซ้ำได้เราควรจัดให้มีวิธีการเฉพาะกิจสำหรับแต่ละวิธี
ตัวอย่างเช่นStringให้ไม่ใช่into_iterหรือiterเพราะมีสองวิธีในการย้ำ: เพื่อย้ำการเป็นตัวแทนในไบต์หรือเพื่อย้ำการเป็นตัวแทนในตัวละคร แต่มีสองวิธี: bytesสำหรับการทำซ้ำไบต์และcharsสำหรับการทำซ้ำอักขระเป็นทางเลือกแทนiterวิธีการ
*ทางเทคนิคเราสามารถทำได้โดยการสร้างลักษณะ แต่เราจำเป็นต้องมีคุณสมบัติimplนั้นสำหรับแต่ละประเภทที่เราต้องการใช้ ในขณะเดียวกันในหลายประเภทอยู่แล้วดำเนินการstdIntoIterator