Bence biraz daha açıklığa kavuşacak bir şey var. Koleksiyon türleri, Vec<T>ve gibi VecDeque<T>, uyguladıkları için into_iterverim yöntemine sahiptir . Tekrarlanan bir tür yaratmamızı durduracak hiçbir şey yok , başka bir tür vermez . Yani, uygular .TIntoIterator<Item=T>Foo<T>TUFoo<T>IntoIterator<Item=U>
Aslında, bazı örnekler vardır std: &Path uygular IntoIterator<Item=&OsStr> ve &UnixListener uygular IntoIterator<Item=Result<UnixStream>> .
Arasındaki fark into_iterveiter
Arasındaki farkı asıl soruya geri dön into_iterve iter. Diğerlerinin belirttiği gibi, fark, belirtilen herhangi bir tip verebilen into_itergerekli bir yöntem olmasıdır . Tipik olarak, eğer bir tip uygularsa , konvansiyonla aynı zamanda iki ad-hoc yöntemi vardır: ve sırasıyla ve verim .IntoIteratorIntoIterator::ItemIntoIterator<Item=I>iteriter_mut&I&mut I
Bunun anlamı, into_iterbağlı bir özellik kullanarak yöntemi olan (yani yinelenebilir) bir tür alan bir işlev oluşturabilmemizdir :
fn process_iterable<I: IntoIterator>(iterable: I) {
for item in iterable {
// ...
}
}
Ancak, yöntem veya yöntem için bir tür gerektiren bir özelliği * kullanamayız , çünkü bunlar yalnızca konvansiyonlardır. Bunun veya ' dan daha yaygın olarak kullanılabilir olduğunu söyleyebiliriz .iteriter_mutinto_iteriteriter_mut
Alternatifler iterveiter_mut
Gözlemlenmesi gereken bir başka ilginç şey ise iter , bir yineleyici elde etmenin tek yolunun olmamasıdır &T. Geleneksel olarak (tekrar), toplama türleri SomeCollection<T>içinde stdvar olan iteryöntem de onların değişmez referans tipleri vardır &SomeCollection<T>uygulamak IntoIterator<Item=&T>. Örneğin, &Vec<T> uygular IntoIterator<Item=&T> , böylece tekrarlamamızı sağlar &Vec<T>:
let v = vec![1, 2];
// Below is equivalent to: `for item in v.iter() {`
for item in &v {
println!("{}", item);
}
Her iki uygulamada v.iter()da eşdeğerse , Rust neden her ikisini de sağlar? Ergonomi için. Gelen döngüler, bu kullanımda biraz daha özlü var daha ; ancak diğer durumlarda, aşağıdakilerden çok daha açıktır :&vIntoIterator<Item=&T>for&vv.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();
Benzer şekilde, fordöngülerde v.iter_mut()şu ile değiştirilebilir &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;
}
Ne zaman sağlanmalı (uygulanmalı) into_iterveiter yöntemler
Türün yinelenecek tek bir “yolu” varsa, her ikisini de uygulamalıyız. Ancak, yinelenebilecek iki veya daha fazla yol varsa, bunun yerine her bir yol için geçici bir yöntem sağlamalıyız.
Örneğin, String yinelemenin iki yolu olmadığı için into_iterne sağlar ne de sağlar iter: bayt cinsinden temsilini yinelemek veya karakterdeki temsilini yinelemek. Bunun yerine, iki yöntem sunar: yönteme alternatif olarak bytesbaytları charsyinelemek ve karakterleri yinelemek için iter.
* Teknik olarak bunu bir özellik oluşturarak yapabiliriz. Ama sonra implkullanmak istediğimiz her tür için bu özelliğe ihtiyacımız var . Bu arada, birçok türü stdzaten uygulamak IntoIterator.