This code works, but I have two questions in comments within the code.
use std::collections::HashMap;
type StringToIntMap = HashMap<String, i32>;
fn main() {
let mut score_map: StringToIntMap = StringToIntMap::new();
score_map.insert("Mark".to_string(), 19);
score_map.insert("Tami".to_string(), 42);
score_map.insert("Amanda".to_string(), 37);
score_map.insert("Jeremy".to_string(), 35);
// Why do I get the error "borrow of moved value" without "&"?
for entry in &score_map {
println!("{:?}", entry);
}
// Is this the best way to find the winner?
// The use of "nobody" seems to complicated.
let nobody = (&"".to_string(), &0i32);
let winner = score_map.iter().fold(nobody, |acc, entry| {
if entry.1 > &acc.1 { entry } else { acc }
});
println!("winner is {}", winner.0);
}
Why do I get the error "borrow of moved value" without &?
This is because a for loop always consumes the thing you iterator over, so without the &, the hash map is consumed. When you include the &, it just consumes the reference, which doesn't do much.
As for the for loop, it's because if you need ownership of the values inside the map, you have to consume the map, and not using an & is the way you do that.
To elaborate on this, in for PAT in EXPR { ... }, the compiler creates an iterator by implicity inserting a call to {EXPR}.into_iter() (IntoIterator::into_iter). For collections, this creates an iterator that deconstructs the collection and yields the individual elements. However, for references to collections, this creates an iterator that merely iterates over references to elements.
You can see that it consumes it because the method takes self rather than &self or &mut self. Additionally, methods that start with into_ will by convention consume the thing it is called on.
Just checking my understanding ... Is it true that I can infer ownership is transferred because the first parameter is self AND HashMap does not implement the Copy trait? IIUC, if it did implement Copy then ownership would not be transferred.
Yes. Or both have ownership of their copied data, if you prefer.
(Incidentally, when making examples or experimenting with Rust's ownership model, it's always a good idea to do so with non-Copy types to ensure you don't mislead yourself or others.)