Have you worked with languages where you have to deal with references or pointers before? If not, you may want to read up on ownership and references. Later on in the book, updating a hash is discussed, including an explanation of what the *freq
(or *count
) is doing.
In brief,
- a
&mut T
is a reference some T
you can override or otherwise modify
-
freq
is a &mut u32
like the annotation says, so it references a u32
somewhere (inside the map's allocated memory, as it happens)
-
*freq
is the memory of the u32
itself
-
*freq += 1
adds 1 to the u32
in-place (inside the map's allocated memory)
Reading the book is a good way to start learning the language in general.
If you know all that, then this is just a question of understanding the API. While it can be slow to look things up one by one when you're starting out, the std
docs are generally quite good. So let's take a look:
// vvvvvvvv annotation
let freq: &mut u32 = freq_vec // HashMap (with an unintuitive name)
.entry(*i) // some Thing
.or_insert(0); // &mut u32, from annotation
HashMap::entry
gives us a HashMap::Entry
:
pub enum Entry<'a, K: 'a, V: 'a> {
Occupied(OccupiedEntry<'a, K, V>),
Vacant(VacantEntry<'a, K, V>),
}
Ignoring all the stuff in <...>
, we can see that it's either occupied or vacant. This is the thing ("some Thing") we called .or_insert
on:
Ensures a value is in the entry by inserting the default if empty, and returns a mutable reference to the value in the entry.
So afterwards we have a &mut u32
directly into the memory that the HashMap
owns, associated with the key *i
. If it was already in the map, that's what's being referenced. If it wasn't in the map before, it was inserted with the value 0, because that's what or_insert(0)
does if the Entry
is Vacant
.
The Entry API, as it's called, is useful for avoiding double-lookups and the like. Contrast:
for i in &some_vec {
let freq = if let Some(freq) = freq_vec.get_mut(i) {
*freq += 1;
freq
} else {
freq_vec.insert(*i, 1);
freq_vec.get_mut(i).unwrap()
};
println!("{:?}", freq)
}
(It should probably be called freq_map
, not freq_vec
.)