Iterators

Chain and Once

You can add a single element to an existing iterator using the once and chain functions. This allows you to include an additional iterator element that might be an exceptional case to the other mapped iterator elements. The chain function stitches two iterators together and the once function produces an iterator with a single element.

(0..5).chain(std::iter::once(6)) // [0, 1, 2, 3, 4, 5]

Zip

If you want to combine the values of two iterators into a set of tuple pairs you can use the zip function.

first_iterator.zip(second_iterator).collect::<Vec<(usize, usize)>>()
// [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]

Functions that Return Iterators

You can return an iterator from a function by directly returning the structure the structure that an iterators yields.

fn return_split(word: &str) -> Split<'_, char> {
  word.split(' ')
}

You can return an iterator from a function in a more readable way by using the impl Iterator syntax. This essentially just dynamically replaces itself with the actually return type above but allows you to specify the iterator return as a generalised iterator with an Item type, this means we can specify in the code below that we expect to receieve back an Iterator that contains a list of &str rather than the more obfuscated Split object containing chars.

fn return_split(word: &str) -> impl Iterator<Item = &str> {
  word.split(' ')
}

Mutable Iterators

You can mutate the objects in a mutable structure with an iterator by using the iter_mut() function. It seems logical that if you mark a structure as mut and then use iter or into_iter the values returned by the iterator should mutate the structure, but this is not the case and causes a world of pain, even if you mark the x inside the closure with mut it will still result in errors because the values from iter cannot be written to.

// wrong :(
let mut x = vec![1, 2, 3, 4];  
x.iter().for_each(|x| *x += 1); // ERROR
// right :)
let mut x = vec![1, 2, 3, 4]; 
x.iter_mut().for_each(|x| *x += 1); // => [2, 3, 4, 5]

When iterating mutably over nested structures all outer and inner structures must use iter_mut regardless of how nested the structure is that is actually changing. Using an iter method on one of the iterations below while changing the inner structure would cause the same mutability and borrowing options seen above.

let mut x = vec![vec![1, 2, 3], vec![4, 5, 6]];   
x
  .iter_mut()
  .for_each(|y| {  
    y
    .iter_mut()
    .for_each(|z| *z += 1)  
}); // => [[2, 3, 4], [5, 6, 7]]