Search code examples
rusthashmapiteratorvec

Why can a Range be collected into a HashMap or Vec in Rust?


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.


Solution

  • Why can a Range be collected into a HashMap or Vec in Rust?

    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>).

    I'm curious about the reason behind this behavior.

    Iterator::collect is a generic operation, it can collect into anything implementing the FromIterator trait, which is the case of Vec and HashMap IFF the iterator returns pairs (2-uples) and the first element of the pair implements Hash + 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 single Result, which will stop at the first Result::Err it encounters and return that, and will otherwise collect into whatevet concrete collection you specify

    I recently encountered a problem

    Why is it a problem?