13.1. Closures: Anonymous Functions that Can Capture Their Environment

Closure definitions will have one concrete type inferred for each of their parameters and for their return value. Those types are then locked into the closure, and we get a type error if we try to use a different type with the same closure.

Capturing the Environment with Closures

Closures can capture values from their environment in three ways, which directly map to the three ways a function can take a parameter: taking ownership, borrowing mutably, and borrowing immutably. These are encoded in the three Fn traits as follows:

All closures implement FnOnce because they can all be called at least once.

If you want to force the closure to take ownership of the values it uses in the environment, you can use the move keyword before the parameter list. There will be more on this in Chapter 16.

Most of the time when specifying one of the Fn trait bounds, you can start with Fn and the compiler will tell you if you need FnMut or FnOnce based on what happens in the closure body.

13.2. Processing a Series of Items with Iterators

In Rust, iterators are lazy, meaning they have no effect until you call methods that consume the iterator to use it up.

The iter method produces an iterator over immutable references.

If we want to create an iterator that takes ownership of v1 and returns owned values, we can call into_iter instead of iter. Similarly, if we want to iterate over mutable references, we can call iter_mut instead of iter .

When using next on iterators , one need to make it mut because next will change the internal states of it. Note that for item in sth.iter() we don’t need to make sth.iter() mutable because for does take ownership of it and make it mut for us behind the scenes.