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_iter
verim yöntemine sahiptir . Tekrarlanan bir tür yaratmamızı durduracak hiçbir şey yok , başka bir tür vermez . Yani, uygular .T
IntoIterator<Item=T>
Foo<T>
T
U
Foo<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_iter
veiter
Arasındaki farkı asıl soruya geri dön into_iter
ve iter
. Diğerlerinin belirttiği gibi, fark, belirtilen herhangi bir tip verebilen into_iter
gerekli 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 .IntoIterator
IntoIterator::Item
IntoIterator<Item=I>
iter
iter_mut
&I
&mut I
Bunun anlamı, into_iter
bağ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 .iter
iter_mut
into_iter
iter
iter_mut
Alternatifler iter
veiter_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 std
var olan iter
yö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 :&v
IntoIterator<Item=&T>
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();
Benzer şekilde, for
dö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_iter
veiter
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_iter
ne 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 bytes
baytları chars
yinelemek ve karakterleri yinelemek için iter
.
* Teknik olarak bunu bir özellik oluşturarak yapabiliriz. Ama sonra impl
kullanmak istediğimiz her tür için bu özelliğe ihtiyacımız var . Bu arada, birçok türü std
zaten uygulamak IntoIterator
.