`fold` values into a HashMap
After reading this article Learning Programming Concepts by Jumping in at the Deep End I can't seem to understand how exactly fold()
is working in this context. Mainly how fold()
knows to grab the word
variable from split()
.
Here's the example:
use std::collections::HashMap;
fn count_words(text: &str) -> HashMap<&str, usize> {
text.split(' ').fold(
HashMap::new(),
|mut map, word| { *map.entry(word).or_insert(0) += 1; map }
)
}
Playground
Rust docs say:
fold()
takes two arguments: an initial value, and a closure with two arguments: an ‘accumulator’, and an element. The closure returns the value that the accumulator should have for the next iteration.
Iterator - fold
So I get the mut map
is the accumulator and I get that split()
returns an iterator and therefore fold()
is iterating over those values but how does fold
know to grab that value? It's being implicitly passed but I cant seem to wrap my head around this. How is that being mapped to the word
variable...
Not sure if I have the right mental model for this...
Thanks!
Solution 1:
but how does
fold
know to grab that value?
fold()
is a method on the iterator. That means that it has access to self
which is the actual iterator, so it can call self.next()
to get the next item (in this case the word, since self
is of type Split
, so its next()
does get the next word). You could imagine fold()
being implemented with the following pseudocode:
fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
Self: Sized,
F: FnMut(B, Self::Item) -> B,
{
let mut accum = init;
while let Some(x) = self.next() {
accum = f(accum, x);
}
accum
}
Ok, the above is not pseudocode, it's the actual implementation.