もう少しはっきりさせたいことがあると思います。コレクションなど、種類、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よりも広く使用できます。iteriter_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は両方を提供するのですか?人間工学用です。でループ、それは使用に簡潔もう少しだより。しかし、他の場合では、よりも明確です:&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();
同様に、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。