Saya pikir ada sesuatu yang perlu diklarifikasi sedikit lagi. Jenis koleksi, seperti Vec<T>dan VecDeque<T>, memiliki into_itermetode yang menghasilkan Tkarena mereka menerapkan IntoIterator<Item=T>. Tidak ada yang menghentikan kita untuk membuat tipe Foo<T>jika yang diulangi, itu akan menghasilkan bukan Ttipe lain U. Yaitu, Foo<T>implementasinya IntoIterator<Item=U>.
Bahkan, ada beberapa contoh di std: &Path alat IntoIterator<Item=&OsStr> dan &UnixListener alat IntoIterator<Item=Result<UnixStream>> .
Perbedaan antara into_iterdaniter
Kembali ke pertanyaan awal tentang perbedaan antara into_iterdan iter. Serupa dengan yang ditunjukkan orang lain, perbedaannya adalah into_itermetode yang diperlukan IntoIteratoryang dapat menghasilkan jenis apa pun yang ditentukan IntoIterator::Item. Biasanya, jika suatu tipe mengimplementasikan IntoIterator<Item=I>, dengan konvensi ia juga memiliki dua metode ad-hoc: iterdan iter_mutyang menghasilkan &Idan &mut I, masing-masing.
Apa yang tersirat adalah bahwa kita dapat membuat fungsi yang menerima tipe yang memiliki into_itermetode (yaitu iterable) dengan menggunakan sifat terikat:
fn process_iterable<I: IntoIterator>(iterable: I) {
for item in iterable {
// ...
}
}
Namun, kita tidak dapat * menggunakan suatu sifat yang terikat untuk meminta suatu tipe untuk memiliki itermetode atau iter_mutmetode, karena itu hanya konvensi. Kita dapat mengatakan bahwa into_iteritu lebih banyak digunakan daripada iteratau iter_mut.
Alternatif untuk iterdaniter_mut
Yang menarik untuk diamati adalah bahwa iteritu bukan satu-satunya cara untuk mendapatkan iterator yang menghasilkan &T. Dengan konvensi (lagi), jenis koleksi SomeCollection<T>di stdmana memiliki itermetode juga memiliki referensi jenis berubah mereka &SomeCollection<T>melaksanakan IntoIterator<Item=&T>. Misalnya, &Vec<T> mengimplementasikan IntoIterator<Item=&T> , sehingga memungkinkan kita untuk beralih &Vec<T>:
let v = vec![1, 2];
// Below is equivalent to: `for item in v.iter() {`
for item in &v {
println!("{}", item);
}
Jika v.iter()setara dengan &vkedua implementasi tersebut IntoIterator<Item=&T>, mengapa Rust menyediakan keduanya? Ini untuk ergonomi. Dalam forloop, ini sedikit lebih ringkas untuk digunakan &vdaripada v.iter(); tetapi dalam kasus lain, v.iter()jauh lebih jelas daripada (&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();
Demikian pula, dalam forloop, v.iter_mut()dapat diganti dengan &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;
}
Kapan harus menyediakan (mengimplementasikan) into_iterdan itermetode untuk suatu jenis
Jika tipe hanya memiliki satu "cara" untuk diulangi, kita harus mengimplementasikan keduanya. Namun, jika ada dua cara atau lebih yang dapat diulangi, kita harus menyediakan metode ad-hoc untuk setiap cara.
Misalnya, Stringtidak menyediakan into_iteratau iterkarena ada dua cara untuk mengulanginya: untuk mengulangi perwakilannya dalam byte atau untuk mengulangi perwakilannya dalam karakter. Alih-alih, ia menyediakan dua metode: bytesuntuk iterasi byte dan charsuntuk iterasi karakter, sebagai alternatif itermetode.
* Yah, secara teknis kita bisa melakukannya dengan menciptakan suatu sifat. Tetapi kemudian kita perlu implsifat itu untuk setiap jenis yang ingin kita gunakan. Sementara itu, banyak tipe yang stdsudah diimplementasikan IntoIterator.