+// You can change `main` to call this function, and you should notice - nothing, no difference in behavior.
+// But we wrote much less boilerplate code!
+
+// Remember that we decided to use the `FnMut` trait above? This means our closure could actually mutate its environment.
+// For example, we can use that to count the digits as they are printed.
+pub fn print_and_count(b: &BigInt) {
+ let mut count: usize = 0;
+ //@ This time, the environment will contain a field of type `&mut usize`, that will be initialized with a mutable reference of
+ //@ `count`. The closure, since it mutably borrows its environment, is able to access this field and mutate `count`
+ //@ through it. Once `act` returns, the closure is destroyed and `count` is no longer borrowed. Because closures compile down
+ //@ to normal types, all the borrow checking continues to work as usually, and we cannot accidentally leak a closure somewhere
+ //@ that still contains, in its environment, a dead reference.
+ b.act(|digit| { println!("{}: {}", count, digit); count = count +1; } );
+ println!("There are {} digits", count);
+}
+
+// ## Fun with iterators and closures
+//@ If you are familiar with functional languages, you are probably aware that one can have lots of fun with iterators and closures.
+//@ Rust provides a whole lot of methods on iterators that allow us to write pretty functional-style list manipulation.
+
+// Let's say we want to write a function that increments every entry of a `Vec` by some number, then looks for numbers larger than some threshold, and prints them.
+fn inc_print_even(v: &Vec<i32>, offset: i32, threshold: i32) {
+ //@ `map` takes a closure that is applied to every element of the iterator. `filter` removes elements
+ //@ from the iterator that do not pass the test given by the closure.
+ //@
+ //@ Since all these closures compile down to the pattern described above, there is actually no heap allocation going on here. This makes
+ //@ closures very efficient, and it makes optimization fairly trivial: The resulting code will look like you hand-rolled the loop in C.
+ for i in v.iter().map(|n| *n + offset).filter(|n| *n > threshold) {
+ println!("{}", i);
+ }
+}
+
+// Sometimes it is useful to know both the position of some element in a list, and its value. That's where the `enumerate` function helps.
+fn print_enumerated<T: fmt::Display>(v: &Vec<T>) {
+ //@ `enumerate` turns an iterator over `T` into an iterator over `(usize, T)`, where the first element just counts the position in the iterator.
+ //@ We can do pattern matching right in the loop header to obtain names for both the position, and the value.
+ for (i, t) in v.iter().enumerate() {
+ println!("Position {}: {}", i, t);
+ }
+}
+
+// And as a final example, one can also collect all elements of an iterator, and put them, e.g., in a vector.
+fn filter_vec_by_divisor(v: &Vec<i32>, divisor: i32) -> Vec<i32> {
+ //@ Here, the return type of `collect` is inferred based on the return type of our function. In general, it can return anything implementing
+ //@ [`FromIterator`](https://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html). Notice that `iter` gives us an iterator over
+ //@ borrowed `i32`, but we want to own them for the result, so we insert a `map` to dereference.
+ v.iter().map(|n| *n).filter(|n| *n % divisor == 0).collect() /*@*/
+}
+
+// **Exercise 10.1**: Look up the [documentation of `Iterator`](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) to learn about more functions
+// that can act on iterators. Try using some of them. What about a function that sums the even numbers of an iterator? Or a function that computes the
+// product of those numbers that sit at odd positions? A function that checks whether a vector contains a certain number? Whether all numbers are
+// smaller than some threshold? Be creative!