もう少しはっきりさせたいことがあると思います。コレクションなど、種類、Vec<T>
およびVecDeque<T>
、持っinto_iter
利回りその方法をT
、彼らが実装しているためIntoIterator<Item=T>
。Foo<T>
反復されるタイプを作成するのを止めるものは何もありません。それが生成されない場合T
、別のタイプが生成されU
ます。つまり、をFoo<T>
実装しIntoIterator<Item=U>
ます。
実際には、いくつかの例がありますstd
:&Path
implements IntoIterator<Item=&OsStr>
と&UnixListener
implements IntoIterator<Item=Result<UnixStream>>
。
違いinto_iter
とiter
into_iter
との違いに関する元の質問に戻りiter
ます。他の人が指摘したのと同様に、違いは、into_iter
でIntoIterator
指定された任意のタイプを生成できる必須メソッドであることIntoIterator::Item
です。典型的には、型実装する場合はIntoIterator<Item=I>
、慣例により、また、2つのアドホック・メソッドがありますiter
し、iter_mut
その収率&I
と&mut I
それぞれ。
暗黙into_iter
のトレイトを使用して、メソッドを持つ型(つまり、反復可能)を受け取る関数を作成できるということです。
fn process_iterable<I: IntoIterator>(iterable: I) {
for item in iterable {
// ...
}
}
しかし、我々はできません*持っているタイプを必要とするためにバインドされた形質使うiter
方法やiter_mut
、彼らはただの慣習だから、方法を。またはinto_iter
よりも広く使用できます。iter
iter_mut
iter
およびの代替iter_mut
観察するもう1つの興味深い点iter
は、それが生成するイテレータを取得する唯一の方法ではないということです&T
。慣例によりSomeCollection<T>
、std
ここiter
でも、メソッドを持つコレクション型には不変の参照型が&SomeCollection<T>
実装されていIntoIterator<Item=&T>
ます。たとえば、&Vec<T>
implements 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()
がと同じである場合、なぜRustは両方を提供するのですか?人間工学用です。でループ、それは使用に簡潔もう少しだより。しかし、他の場合では、よりも明確です:&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();
同様に、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
メソッドを提供するタイミング
型が繰り返される「ウェイ」が1つしかない場合は、両方を実装する必要があります。ただし、2つ以上の方法で繰り返すことができる場合は、代わりにそれぞれの方法にアドホックメソッドを提供する必要があります。
たとえば、String
は、を提供することinto_iter
も提供することもしないiter
ため、反復する2つの方法があります。その表現をバイト単位で反復するか、文字単位で反復するかです。代わりに、メソッドの代わりに、bytes
バイトchars
を反復するためと文字を反復するための2つのメソッドを提供しますiter
。
*そうですね、技術的には、特性を作成することでそれを行うことができます。ただし、impl
使用するタイプごとにその特性を設定する必要があります。その間、多くのタイプがstd
すでに実装していますIntoIterator
。