I wrote a working solution to the third proposed exercise in section 8.3 of The Book, but some of the behavior defies my intuition. Specifically, it appears that I'm able to mutate a vector that appears to be instantiated as immutable.
I've included the portions of the code that I believe are relevant, eliding the portions of code that do not interact with the Vecs stored in the HashMap.
I've engaged in some speculation after the code block, but I could really use a more sure-footed explanation of what's actually happening.
// Start by declaring a new HashMap. This is where the mystery begins for me.
let mut departments: HashMap<String, Vec<String>> = HashMap::new();
// This code deals with getting user input from stdin and has been elided
// ...
// Match the first string slice
match args[0] {
// Add an employee to a department in the HashMap
"add" => {
// POINT OF INTEREST 1
// Adding a department that isn't already in the HashMap will cause a new empty
// vector to be inserted at the newly created key
let list = departments.entry(args[2].to_string()).or_insert(Vec::new());
// In any case, we insert the employee's name into the vector associated with
// whatever department we got from stdin
list.push(args[1].to_string());
}
// List employees
"who" => match args[1] {
// List all employees in every department, employees shown in alphabetical order
"all" => {
for (department, employees) in &mut departments {
// POINT OF INTEREST 2
// Why am I allowed to sort this vector? The artifact underlying the reference
// was never explicitly made mutable.
employees.sort();
for ee in employees {
println!("{}: {}", department, ee);
}
}
}
// List all employees in a given department, employees shown in alphabetical order
dept => {
let employees = departments.get_mut(dept);
match employees {
Some(entries) => {
// POINT OF INTEREST 3
// This one is seems the least mysterious to me, since I get the value
// of the HashMap at `dept` through `.get_mut()`.
println!("{}:", dept);
entries.sort();
for ee in entries {
println!("\t{}", ee);
}
}
_ => (),
}
}
}
}
Hypothesis 1: At POINT OF INTEREST 1, my call to .or_insert() returns a mutable reference to a new vector, and this is why later calls to .sort() on values in the HashMap work.
This does not seem like the likely answer! In the beginning, I declared departments to be of the type HashMap<String, Vec<String>>, not HashMap<String, &mut Vec<String>>.
Hypothesis 2: When I declare departments as mutable, its keys and values inherit that mutability. This also seems unlikely, as nothing in my (very limited) experience has suggested such a thing is a feature of Rust. I also like to think that if that were explicitly stated in the first 8 chapters of The Book it would have caught my attention, but I've been known to skim over important details before.