fn main() { let v1 = vec![1, 2, 3]; let v1_iter = v1.iter(); // The loop takes ownership of the iterator "v1_iter" and makes it mutable under the hood, // with this process "v1_iter" get consumed. for val in v1_iter { println!("Got: {val}"); } // We declare it as mut because calling next(), consumes an element from the iterator and // as a result it's internal state changes. When we implement the Iterator trait for any // type, we generally have to always implement the next method, as the other methods defined // in this trait call next() within their implementations. Mehtods which call next() are known // as consuming adapters. let mut v1_iter = v1.iter(); assert_eq!(v1_iter.next(), Some(&1)); assert_eq!(v1_iter.next(), Some(&2)); assert_eq!(v1_iter.next(), Some(&3)); assert_eq!(v1_iter.next(), None); // Iterator adapters are methods that do not consume an interator, instead produce different // iterators by changing some aspect of the original iterator. // Iterator adapters are lazy, meaning the closure in the below line won't be called as long // as this iterator is NOT CONSUMED. We will get a warning for the same (if we don't use // .collect() or any method that consumes the iterator. // |------Collection-| |-----Iterator----------| |--- consumes the iterator & gives collection let v1_iter: Vec<i32> = v1.iter().map(|x| x + 1).collect(); assert_ne!(v1, v1_iter); filters_by_size(); println!("done.");}// IMPORTANT:// The values that we get from the calls of next() are immutable references to the values in the// vector. If we need an iterator which takes ownership of v1 (the vector) and returns owned values// we use into_iter(), if need to iterate over mutable references, we use iter_mut()#[derive(Debug, PartialEq)]struct Shoe { size: u32, style: String,}// The closure here captures "shoe_size" from it's environment i.e. the scope of shoes_in_size()fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> { shoes.into_iter().filter(|s| s.size == shoe_size).collect()}fn filters_by_size() { let shoes = vec![ Shoe { size: 10, style: String::from("kkd") }, Shoe { size: 13, style: String::from("kkd") }, Shoe { size: 10, style: String::from("kkd") }, ]; let in_my_size = shoes_in_size(shoes, 10); assert_eq!(in_my_size, vec![ Shoe { size: 10, style: String::from("kkd") }, Shoe { size: 10, style: String::from("kkd") }, ]);}