I recently encountered a problem while learning about iterators. I attempted to convert a list of numbers into a Vec
, but when I changed the type to HashMap
, no error occurred. For example:
type Test = Vec<(usize, Vec<usize>)>;
// type TestHashMap = HashMap<usize, Vec<usize>>;
...
fn make_heavy_things() -> Test {
let x = (1..=10).map(|v| (v, vec![v])).collect();
x
}
// x can be a HashMap or Vec depending on the return type
Both types seem to work without any issues, and common methods like len()
work as expected. I'm curious about the reason behind this behavior.
A range can not be collected to a hashmap, a hashmap needs pairs of key and value, which a range is not, your iterator is not a range it's a range mapped to a pair of
(usize, Vec<usize>)
.Iterator::collect
is a generic operation, it can collect into anything implementing theFromIterator
trait, which is the case ofVec
andHashMap
IFF the iterator returns pairs (2-uples) and the first element of the pair implementsHash + Eq
.This provides a type-safe one-stop-shop for converting iterators to various forms, and allows for useful compositions, for instance you can collect iterators of
Result
into a singleResult
, which will stop at the firstResult::Err
it encounters and return that, and will otherwise collect into whatevet concrete collection you specifyWhy is it a problem?