Iterators

Rusts iterators are:

  • Lazy

  • Pervasive

  • Potentially infinite

Where Do They Come From?

  • Collections like Vec<T> have an iter() function which yields an iterator.

  • Things like std::net::TcpListener which provides an iterator of TcpStreams via incoming().

  • Functions like str::split and str::split_n

  • Iterators can be implemented on other structures as well.

Owned iterators

fn main() {
    let vec = vec![1,2,3];
    let iter = vec.into_iter();

    for i in iter {
        println!("{}", i);
    }

    //println!("{:?}", vec); (1)
}
1this won’t work

Borrowed iterators

fn main() {
    let vec = vec![1,2,3];
    let iter = vec.iter();

    for i in iter {
        println!("{}", i);
    }

    println!("{:?}", vec);
}

Mutably Borrowed iterators

fn main() {
    let mut vec = vec![1,2,3];
    let iter_mut = vec.iter_mut();
    
    for i in iter_mut {
       *i += 1
    }

    println!("{:?}", vec);
}

Conventions

OwnedBorrowedMutably borrowed

.into_iter()

.iter()

.iter_mut()

Common Uses

next()

Iterators can be advanced manually:

fn main() {
    let items = vec![0, 1, 2];
    let mut iterator = items.into_iter();
    println!("{:?}", iterator.next());
    println!("{:?}", iterator.next());
    println!("{:?}", iterator.next());
    println!("{:?}", iterator.next());
}

Combinators: map()

Transform items as they are evaluated:

fn main() {
    let fizzbuzz = (0..10_000)
        .map(|x| match x {
            x if x % 15 == 0 => String::from("Fizzbuzz"),
            x if x % 3  == 0 => String::from("Fizz"),
            x if x % 5  == 0 => String::from("Buzz"),
            x => format!("{}", x),
        });
    for item in fizzbuzz {
        println!("{}", item);
    }
}

Combinators: filter()

Filter out unwanted values, skipping further computation on them:

fn main() {
    let evens = (0..10_000)
        .filter(|x| x % 2 == 0);
    for item in evens {
        println!("{}", item);
    }
}