Iterator vs IntoIterator untuk rata
Saya bermain-main dengan iterator dan saya telah menggunakannya Flattenuntuk lebih memahami cara kerja iterator. Contoh ini:
assert_eq!(vec![1, 2].iter().flatten().count(), 2);
Tidak mengkompilasi dan memberikan kesalahan (yah kesalahan utama yang menjadi perhatian):
error[E0277]: `&{integer}` is not an iterator
--> src/lib.rs:59:38
|
59 | assert_eq!(vec![1, 2].iter().flatten().count(), 2);
| ^^^^^^^ `&{integer}` is not an iterator
|
= help: the trait `std::iter::Iterator` is not implemented for `&{integer}`
= note: required because of the requirements on the impl of `std::iter::IntoIterator` for `&{integer}`
Yang membingungkan saya adalah sepertinya Flattenmembutuhkan bersarang Itemuntuk diterapkan IntoIterator. Saya mengkonfirmasi ini di rustdocs, di mana mereka menyatakan
pub struct Flatten<I>
where
I: Iterator,
<I as Iterator>::Item: IntoIterator
Baru saja menyiapkan dokumen, IntoIterator hanya menyediakan cara untuk menentukan bagaimana suatu tipe diubah menjadi iterator. Mengapa sifat itu tidak bisa terikat <I as Iterator>::Item: Iterator? Tentunya jika item bersarang diimplementasikan Iterator, maka kita mendapatkan yang sama Flattenkarena item bersarang haruslah iterator itu sendiri. Perbedaan / manfaat apa yang dibawanya untuk digunakan IntoIterator?
Jawaban
Memerlukan IntoIteratordaripada Iteratormemungkinkan Anda meratakan koleksi koleksi selain koleksi iterator.
Jenis koleksi, misalnya Vec, berbeda dari jenis iterator, jadi jika flattendiperlukan barang yang akan Iterators Anda tidak bisa meratakan Vecdari Vecs.
IntoIteratormewakili tipe yang bisa diubah menjadi iterator, seperti Vecatau banyak koleksi lainnya (atau iterator!). Jadi ini, misalnya, berfungsi:
fn main() {
let nested_vec: Vec<Vec<i32>> = vec![vec![1, 2], vec![3, 4]];
let flat_vec: Vec<i32> = nested_vec.into_iter().flatten().collect();
println!("{:?}", flat_vec);
}
Anda dapat mencoba contoh ini di Playground . Menggunakan di into_iter()atas daripada iter()memastikan kita mengulang i32s, bukan referensi ke i32s. (Terima kasih Cerberus untuk menyarankan into_iter()alih-alih copied().)
(Anda dapat melihat beberapa jenis lagi dengan IntoIteratorpenerapan di bagian "Penerapan pada Jenis Asing" di dokumen .)