Here is some code from an exercise. I dont understand why the .map does not require a reference to x when .filter does. Why is the (immutable) iterator allowed to change the value of x?
The difference is the ownership. With filter, you get to look at the value, but the iterator still needs it in case you return true. This is represented by giving you a borrow of the value. Whereas with map, the iterator will give you ownership of the value, since it doesn't need the value after giving it to you.
Note that v isn't modified. v.iter() creates an iterator that yields &i32s (Item = &i32). So the consumer of the iterator, including any adapters like map, don't own the original i32s. They do own the references themselves (note that the adapters almost always work with a generic Item which may or may not be a reference or otherwise implement Copy, etc).
The point of map is to infallibly change each of the items being returned from the iterator -- perhaps even changing their type, not just their value. You could have .map(|x| x.to_string()) for example.
filter on the other hand just needs to be able to say "keep or discard". If it said "keep" and took ownership of the Item, it would have to give ownership back -- otherwise the Item would drop at the end of the closure. (Again, it is generic enough it doesn't know if Item is Copy or not.)
There is an adapter that does this ownership dance: filter_map.
v.iter()
.filter_map(|x| match x % 2 {
0 => Some(x.pow(2)),
_ => None,
})
.sum()
(It can still return a different value or even type.)