Iterators and Ownership

    Traits are like interfaces: they describe behavior (methods) for a type. The trait simply says that you can call next until you get None back:

    You use this trait like this:

    1. fn main() {
    2. let v: Vec<i8> = vec![10, 20, 30];
    3. let mut iter = v.iter();
    4. println!("v[0]: {:?}", iter.next());
    5. println!("v[1]: {:?}", iter.next());
    6. println!("v[2]: {:?}", iter.next());
    7. }

    What is the type returned by the iterator? Test your answer here:

    The Iterator trait tells you how to iterate once you have created an iterator. The related trait IntoIterator tells you how to create the iterator:

    1. #![allow(unused)]
    2. fn main() {
    3. type Item;
    4. type IntoIter: Iterator<Item = Self::Item>;
    5. fn into_iter(self) -> Self::IntoIter;
    6. }
    7. }

    The syntax here means that every implementation of IntoIterator must declare two types:

    • IntoIter: the Iterator type returned by the into_iter method.

    Note that IntoIter and Item are linked: the iterator must have the same Item type, which means that it returns

    Now that we know both Iterator and IntoIterator, we can build for loops. They call into_iter() on an expression and iterates over the resulting iterator:

    1. fn main() {
    2. let v: Vec<String> = vec![String::from("foo"), String::from("bar")];
    3. for word in &v {
    4. println!("word: {word}");
    5. }
    6. for word in v {
    7. println!("word: {word}");
    8. }

    What is the type of in each loop?

    Experiment with the code above and then consult the documentation for impl IntoIterator for &Vec and to check your answers.