## Iterators and Closures

• Basic iterators

• Basic closures

• The full story is much complicated; we will cover it extensively later in the course

## Iterators

• Value that lazily produces values via a .next() method. The .next() method returns an Option: Some while the iterator is still running, None when it is done

• Obvious example is via the .. operator:

 let mut i = 0..3;
while let Some(n) = i.next() {
println!("{}", n);
}


This is exactly the same as

 for n in 0..3 {
println!("{}", n);
}

• Rust .. excludes the last value, like C. Use ..= to include it.

• A whole pile of methods exist for working with iterators, for example

 println!("{}", (1..5).sum());


Many methods make a new iterator from an old, for example

 for i in (0..5).rev() {
println!("{}", i);
}

• Iterators enable a "functional" style of programming; chain them together to produce a desired value instead of writing explicit loops

## Closures

• Anonymous functions ("lambdas") that can reference local variables

// Squaring function.
|n| n * n

• Unlike fn, type inference is attempted on closure arguments and result

• Type is almost "first-class": values can be stored in variables, passed around, etc

• Normally use with methods that want to do a computation as part of their action

let g2 = (1..5).map(|n| n * n).sum();