Extend<&'a (K, V)> for HashMap<K, V, S>

Is there any reason why we are implementing Extend<(&'a K, &'a V)> for HashMap<K, V, S>, but there is no implementation of Extend<&'a (K, V)> for HashMap<K, V, S> in the standard library?

It is really strange, when you can do something like this:

fn main() {
    use std::collections::HashMap;
    let mut map = HashMap::new();
    let some_vec = vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50)];

    // It's OK
    map.extend(some_vec.iter().map(|&(k, v)| (k, v)));

    println!("{:?}", map);
}

But you can not do something like this:

fn main() {
    use std::collections::HashMap;
    let mut map = HashMap::new();
    let some_vec = vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50)];

    map.extend(&some_vec);     // It's error
    map.extend(&some_vec[..]); // It's also error
    println!("{:?}", map);
}

P.S. K: Copy, V: Copy, S: BuildHasher

I think the reasoning is that HashMap::iter() returns an impl Iterator<Item = (&K, &V)>, so you can do something like this my_hashmap.extend(other_hashmap.iter()) when copying the items is trivial. Otherwise you need to call clone() explicitly.

This is the justification from RFC 839:

Alternatives

The Cloneian Candidate

This proposal is artificially restricting itself to Copy rather than full Clone as a concession to the general Rustic philosophy of Clones being explicit. Since this proposal is largely motivated by simple shuffling of primitives, this is sufficient. Also, because Copy: Clone , it would be backwards compatible to upgrade to Clone in the future if demand is high enough.

1 Like

You can also

     // It's OK
-    map.extend(some_vec.iter().map(|&(k, v)| (k, v)));
+    map.extend(some_vec.iter().copied());
4 Likes