Get the Vec of owned values from a HashMap - rust

An algorithm I wrote builds a temporary HashMap. Once it's finished, I'm only interested in the values of the hashmap, so I'd like to transfer ownership of the values from the HashMap<K, V> to a Vec<V>.
With a simplified example hashmap:
fn main() {
use std::collections::HashMap;
let mut h: HashMap<_, _> = HashMap::new();
h.insert(1, "foo".to_owned());
}
I can do:
let vals: Vec<&String> = h.values().collect(); - which is short and sweet, but the hashmap still owns the values;
let vals: Vec<String> = h.values().cloned().collect() (as in this question) - the result is what I need, but I was taught to avoid the extra clones;
let vals: Vec<String> = h.into_iter().map(|(_k, v)| v).collect(); - does what I need without a clone, but is a bit ugly.
The actual values are a mid-sized struct ({String, Vec<String>}, under a KB total).
Should I default to avoiding clone in this case or is it premature optimization? Is there an idiomatic way to do this that I'm missing?

.into_iter().map(|(_, v)| v) is the idiomatic way to do it. That not ugly at all.
If you want you could do:
use std::collections::hash_map;
use std::collections::HashMap;
use std::iter::{ExactSizeIterator, FusedIterator};
struct IntoValues<K, V> {
iter: hash_map::IntoIter<K, V>,
}
impl<K, V> IntoValues<K, V> {
fn new(map: HashMap<K, V>) -> Self {
Self {
iter: map.into_iter(),
}
}
}
impl<K, V> Iterator for IntoValues<K, V> {
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(_, v)| v)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<K, V> ExactSizeIterator for IntoValues<K, V> {}
impl<K, V> FusedIterator for IntoValues<K, V> {}
trait HashMapTool {
type IntoValues;
type Item;
fn into_values(self) -> Self::IntoValues;
}
impl<K, V> HashMapTool for HashMap<K, V> {
type Item = V;
type IntoValues = IntoValues<K, V>;
fn into_values(self) -> Self::IntoValues {
IntoValues::new(self)
}
}
fn main() {
let mut h: HashMap<_, _> = HashMap::new();
h.insert(1, "foo".to_owned());
let _vals: Vec<_> = h.into_values().collect();
}

Note that as of Rust 1.54.0, the into_values method has been implemented for HashMap and BTreeMap in the standard library.
fn main() {
let mut h: HashMap<i32, String> = HashMap::new();
h.insert(1, "foo".to_owned());
let _vals: Vec<String> = h.into_values().collect();
}
https://github.com/rust-lang/rust/blob/master/RELEASES.md#stabilized-apis-6

Related

Generic that could be object of type or reference of type

Given a struct and trait:
// Minimal version of the actual data structure and trait
trait MyTrait {
fn blub(&mut self);
}
struct MyStruct;
impl MyTrait for MyStruct {
fn blub(&mut self) {
println!("Blub!");
}
}
I would like to create a struct that can hold an object that implements MyTrait:
impl<T> Foo<T>
where
T: MyTrait,
{
fn new(t: T) -> Self {
Self { t }
}
fn run(&mut self) {
// Execute `blub` of `t`.
// Something like:
self.t.blub();
}
}
So far, that's easy. Now comes the crux: I want to accept both owned and mutably referenced types, like this:
fn main() {
let t0 = MyStruct;
let mut f0 = Foo::new(t0);
f0.run();
let mut t1 = MyStruct;
let mut f1 = Foo::new(&mut t1);
f1.run();
}
The code here of course doesn't work, because &mut MyStruct does not implement MyTrait.
In theory, this should be possible though, because MyTrait::blub takes &mut self, which is compatible with both owned and mutably borrowed types.
This is how far I've come. It works, but has two problems:
It has a pointless second generic
It requires PhantomData
use std::{borrow::BorrowMut, marker::PhantomData};
// Minimal version of the actual data structure and trait
trait MyTrait {
fn blub(&mut self);
}
struct MyStruct;
impl MyTrait for MyStruct {
fn blub(&mut self) {
println!("Blub!");
}
}
// Object that shall carry objects OR mutable references of type `MyTrait`
struct Foo<T, U> {
t: T,
_p: PhantomData<U>,
}
impl<T, U> Foo<T, U>
where
T: BorrowMut<U>,
U: MyTrait,
{
fn new(t: T) -> Self {
Self { t, _p: PhantomData }
}
fn run(&mut self) {
self.t.borrow_mut().blub();
}
}
fn main() {
let t0 = MyStruct;
let mut f0 = Foo::new(t0);
f0.run();
let mut t1 = MyStruct;
let mut f1: Foo<_, MyStruct> = Foo::new(&mut t1);
f1.run();
}
Blub!
Blub!
Is there a way to implement this more elegantly?
The only other elegant-ish way I have seen so far is to impl MyTrait for &mut MyStruct. Sadly, I do not own the trait or type, so I cannot do that. Although please tell me if my attempts here are misguided and this entire thing is an XY problem; and the actual thing I should do is to report this problem in said library so they can add that impl.
The simplest way is probably to add another implantation of MyTrait for &mut MyStruct.
impl MyTrait for &mut MyStruct {
fn blub(&mut self) {
println!("Blub!");
}
}
If you dont have access to the struct or trait, you can use an enum to manage the Owned and Borrowed versions and implement Deref/DerefMut to keep the usage of t the same.
enum Container<'a, T> {
Owned(T),
Borrowed(&'a mut T)
}
impl<'a, T: MyTrait> From<T> for Container<'a, T> {
fn from(t: T) -> Self {
Self::Owned(t)
}
}
impl<'a, T: MyTrait> From<&'a mut T> for Container<'a, T> {
fn from(t: &'a mut T) -> Self {
Self::Borrowed(t)
}
}
impl<'a, T> Deref for Container<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
Self::Owned(o) => o,
Self::Borrowed(o) => o
}
}
}
impl<'a, T> DerefMut for Container<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Self::Owned(o) => o,
Self::Borrowed(o) => o
}
}
}
struct Foo<'a, T> {
t: Container<'a, T>
}
impl<'a, T> Foo<'a, T>
where
T: MyTrait,
{
fn new(t: impl Into<Container<'a, T>>) -> Self {
Self{ t: t.into() }
}
fn run(&mut self) {
self.t.blub();
}
}
Other solutions I found:
This one doesn't require looking at an enum at runtime, it solves types at compile time:
use std::marker::PhantomData;
// Minimal version of the actual data structure and trait
trait MyTrait {
fn blub(&mut self);
}
struct MyStruct;
impl MyTrait for MyStruct {
fn blub(&mut self) {
println!("Blub!");
}
}
trait MyTraitFrom<'a, T> {
fn mytrait_from(value: &'a mut T) -> Self;
}
impl<'a, T: MyTrait> MyTraitFrom<'a, T> for &'a mut T {
fn mytrait_from(value: &'a mut T) -> Self {
value
}
}
impl<'a, T: MyTrait> MyTraitFrom<'a, &'a mut T> for &'a mut T {
fn mytrait_from(value: &'a mut &'a mut T) -> Self {
let value: &'a mut T = value;
value
}
}
struct Foo<T, U> {
t: T,
_p: PhantomData<U>,
}
impl<'a, T: 'a, U: 'a> Foo<T, U>
where
&'a mut U: MyTraitFrom<'a, T>,
U: MyTrait,
{
fn new(t: T) -> Self {
Self { t, _p: PhantomData }
}
fn run(&'a mut self) {
let u: &'a mut U = MyTraitFrom::mytrait_from(&mut self.t);
u.blub();
}
}
fn main() {
let t0 = MyStruct;
let mut f0 = Foo::new(t0);
f0.run();
let mut t1 = MyStruct;
let mut f1 = Foo::new(&mut t1);
f1.run();
}
Blub!
Blub!

Lifetime conflicts when implementing IntoIterator to iterate over an inner collection [duplicate]

I am trying to create an mutable iterator for a vector of type: Vec<Vec<(K, V)>>
The iterator code:
pub struct IterMut<'a, K: 'a, V: 'a> {
iter: &'a mut Vec<Vec<(K, V)>>,
ix: usize,
inner_ix: usize,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
while self.iter.len() < self.ix {
while self.iter[self.ix].len() < self.inner_ix {
self.inner_ix += 1;
let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
return Some((&k, &mut v));
}
self.ix += 1;
}
return None;
}
}
The error I get is:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:16:42
|
16 | let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
| ^^^^^^^^^^^^^^^^^^
|
help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<(&'a K, &'a mut V)>
--> src/main.rs:11:5
|
11 | fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
| ^
Apparently I have lifetime problems, but I don't know how to tell the compiler that this should work.
Is this how you should implement the mutable iterator or is there a better way?
When debugging cryptic error messages, I've found it easier to try and isolate the issue as much as possible.
The first step is to break the expression into its essential constituents, let's start by splitting the indexing steps:
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
while self.iter.len() < self.ix {
while self.iter[self.ix].len() < self.inner_ix {
self.inner_ix += 1;
let outer: &'a mut Vec<_> = self.iter;
let inner: &'a mut Vec<_> = &mut outer[self.ix];
let (ref k, ref mut v) = inner[self.inner_ix];
return Some((&k, &mut v));
}
self.ix += 1;
}
return None;
}
The Index trait assumes that the lifetime of its output is linked to that of its receiver, so to get a 'a lifetime we need the receiver to have a &'a lifetime, and it propagates upward, leading to the above code.
However there's an issue here: let outer: &'a mut Vec<_> = self.iter; will not compile because mutable references are not Copy.
So, how does one get a mutable reference from a mutable reference (which must be possible since IndexMut gets a mutable reference)?
One uses re-borrowing: let outer: &'a mut Vec<_> = &mut *self.iter;.
And, oh:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> <anon>:16:45
|
16 | let outer: &'a mut Vec<_> = &mut *self.iter;
| ^^^^^^^^^^^^^^^
|
The reborrowed reference is not valid for 'a, it's valid only for the (unnamed) lifetime of self!
Why Rust? Why?
Because doing otherwise would be unsafe.
&mut T is guaranteed NOT to be aliasing, however your method could create aliasing references (if you forgot to advance the index):
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
let (ref k, ref mut v) = self.iter[self.ix][self.inner_ix];
return Some((&k, &mut v));
}
And even if you don't, there's not guarantee that you don't have a rewind method that would allow "stepping back".
TL;DR: You were about to step on a landmine, you were steered toward Stack Overflow instead ;)
Alright, but how do you implement the iterator!.
Well, using iterators, of course. As Shepmaster (briefly) answers, there is the equivalent in the standard library already in the guise of FlatMap. The trick is to use existing iterators for the nitty-gritty details!
Something like:
use std::slice::IterMut;
pub struct MyIterMut<'a, K: 'a, V: 'a> {
outer: IterMut<'a, Vec<(K, V)>>,
inner: IterMut<'a, (K, V)>,
}
Then you consume from inner as long as it provides items, and when empty you refill it from outer.
impl<'a, K, V> MyIterMut<'a, K, V> {
fn new(v: &'a mut Vec<Vec<(K, V)>>) -> MyIterMut<'a, K, V> {
let mut outer = v.iter_mut();
let inner = outer.next()
.map(|v| v.iter_mut())
.unwrap_or_else(|| (&mut []).iter_mut());
MyIterMut { outer: outer, inner: inner }
}
}
impl<'a, K, V> Iterator for MyIterMut<'a, K, V> {
type Item = (&'a K, &'a mut V);
#[inline]
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
loop {
match self.inner.next() {
Some(r) => return Some((&r.0, &mut r.1)),
None => (),
}
match self.outer.next() {
Some(v) => self.inner = v.iter_mut(),
None => return None,
}
}
}
}
A quick test case:
fn main() {
let mut v = vec![
vec![(1, "1"), (2, "2")],
vec![],
vec![(3, "3")]
];
let iter = MyIterMut::new(&mut v);
let c: Vec<_> = iter.collect();
println!("{:?}", c);
}
Prints:
[(1, "1"), (2, "2"), (3, "3")]
as expected, so it's not completely broken, but I wish I did not have to rely on the &[] is 'static trick (ie, that std::slice::IterMut implemented Default).
You've provided no reason that you are reimplementing the standard Iterator::flat_map, so I'd just use that and another map to remove the mutability you don't need:
fn main() {
let mut a: Vec<Vec<(u8, u8)>> = Default::default();
let c = a.iter_mut()
.flat_map(|x| x.iter_mut())
.map(|&mut (ref a, ref mut b)| (a, b))
.count();
println!("{}", c);
}
Once you have that, you can just return the iterator in one of the many ways.
#[derive(Debug, Default)]
struct Thing<K, V>(Vec<Vec<(K, V)>>);
impl<K, V> Thing<K, V> {
fn iter_mut<'a>(&'a mut self) -> Box<Iterator<Item = (&'a K, &'a mut V)> + 'a> {
Box::new(self.0
.iter_mut()
.flat_map(|x| x.iter_mut())
.map(|&mut (ref a, ref mut b)| (a, b)))
}
}
fn main() {
let mut a = Thing::<u8, u8>::default();
let c = a.iter_mut().count();
println!("{}", c);
}

Rust lifetime issue with manually dropped reference wrapper

I'm trying to write a class in Rust with custom drop logic that wraps a mutable reference, but no matter what I do, I can't get the lifetimes to work out, and the compiler error messages haven't helped. Can anyone tell what I'm doing wrong, and how to fix it?
Note: I already tried every modification to this code that I could think of, such as removing or reversing the 'b: 'a constraint, but no matter what I do, the compiler produces one kind of inscrutable lifetime error message or another.
pub struct MapRef<'a, K: Eq + Hash, V>{
p: &'a mut HashMap<K, V>,
}
impl<'a, K: Eq + Hash, V> MapRef<'a, K, V> {
pub fn new(p: &'a mut HashMap<K, V>) -> Self {Self{p}}
}
impl<'a, K: Eq + Hash, V> MapRef<'a, K, V> {
pub fn reborrow<'b: 'a>(&'b mut self) -> MapRef<'b, K, V> {
Self::new(self.p)
}
}
impl<'a, K: Eq + Hash, V> Drop for MapRef<'a, K, V> {
fn drop(&mut self) {
println!("dropping ref");
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test() -> Result<(), String> {
let mut m: HashMap<(), ()> = HashMap::new();
let mut r1 = MapRef::new(&mut m);
{
let r2 = r1.reborrow();
}
Ok(())
}
}
Example error message:
|
37 | let r2 = r1.reborrow();
| ^^ borrowed value does not live long enough
...
41 | }
| -
| |
| `r1` dropped here while still borrowed
| borrow might be used here, when `r1` is dropped and runs the `Drop` code for type `util::MapRef`
It turns out that the reason the compiler suggests adding the erroneous 'b: 'a constraint is because the Self in Self::new is implicitly referring to the 'a lifetime. The solution is to change Self::new to MapRef::new, which allows you to drop the bad constraint.
impl<'a, K: Eq + Hash, V> MapRef<'a, K, V> {
pub fn reborrow<'b>(&'b mut self) -> MapRef<'b, K, V> {
MapRef::new(self.p)
}
}
Note that 'b can now be elided, but I left it in here for clarity.

Rust function that accepts either HashMap and BtreeMap

fn edit_map_values(
map1: &mut HashMap<String, i128> || &mut BTreeMap<String, i128>){
for tuple in map1.iter_mut() {
if !map1.contains_key(&"key1") {
*tuple.1 += 1;
}
}
map1.insert(&"key2", 10);
}
How do I write one function that accepts either HashMap and BtreeMap like in the example above?
It is possible to abstract over types by using traits and for your specific use-case, you can take a look at this more constrained example.
use core::{borrow::Borrow, hash::Hash};
use std::collections::{BTreeMap, HashMap};
trait GenericMap<K, V> {
fn contains_key<Q>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq + Ord;
fn each_mut<F>(&mut self, cb: F)
where
F: FnMut((&K, &mut V));
fn insert(&mut self, key: K, value: V) -> Option<V>;
}
impl<K, V> GenericMap<K, V> for HashMap<K, V>
where
K: Eq + Hash,
{
fn contains_key<Q>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq + Ord,
{
self.contains_key(k)
}
fn each_mut<F>(&mut self, mut cb: F)
where
F: FnMut((&K, &mut V)),
{
self.iter_mut().for_each(|x| cb(x))
}
fn insert(&mut self, key: K, value: V) -> Option<V> {
self.insert(key, value)
}
}
impl<K, V> GenericMap<K, V> for BTreeMap<K, V>
where
K: Ord,
{
fn contains_key<Q>(&self, k: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq + Ord,
{
self.contains_key(k)
}
fn each_mut<F>(&mut self, mut cb: F)
where
F: FnMut((&K, &mut V)),
{
self.iter_mut().for_each(|x| cb(x))
}
fn insert(&mut self, key: K, value: V) -> Option<V> {
self.insert(key, value)
}
}
fn edit_map_values<T: GenericMap<String, i128>>(map: &mut T) {
map.each_mut(|(k, v)| {
if k != "key1" {
*v += 1;
}
});
map.insert("key2".into(), 10);
}
fn main() {
let mut hm: HashMap<String, i128> = [("One".into(), 1), ("Two".into(), 2)]
.iter()
.cloned()
.collect();
let mut btm: BTreeMap<String, i128> = [("Five".into(), 5), ("Six".into(), 6)]
.iter()
.cloned()
.collect();
dbg!(&hm);
dbg!(&btm);
edit_map_values(&mut hm);
edit_map_values(&mut btm);
dbg!(&hm);
dbg!(&btm);
}
Way back before the 1.0 release, there used to be Map and MutableMap traits, but they have been removed before stabilization. The Rust type system is currently unable to express these traits in a nice way due to the lack of higher kinded types.
The eclectic crate provides experimental collection traits, but they haven't been updated for a year, so I'm not sure they are still useful for recent versions of Rust.
Further information:
Does Rust have Collection traits?
No common trait for Map types? (Rust language forum)
Associated type constructors, part 1: basic concepts and introduction (blog post by Niko Matsakis)
Generic associated type RFC
While there is no common Map trait, you could use a combination of other traits to operate on an Iterator to achieve similar functionality. Although this might not be very memory efficient due to cloning, and also a bit involved depending on the kind of operation you are trying to perform. The operation you tried to do may be implemented like this:
fn edit_map_values<I>(map: &mut I)
where
I: Clone + IntoIterator<Item = (String, i128)> + std::iter::FromIterator<(String, i128)>,
{
// Since into_iter consumes self, we have to clone here.
let (keys, _values): (Vec<String>, Vec<_>) = map.clone().into_iter().unzip();
*map = map
.clone()
.into_iter()
// iterating while mutating entries can be done with map
.map(|mut tuple| {
if !keys.contains(&"key1".to_string()) {
tuple.1 += 1;
}
tuple
})
// inserting an element can be done with chain and once
.chain(std::iter::once(("key2".into(), 10)))
.collect();
// removing an element could be done with filter
// removing and altering elements could be done with filter_map
// etc.
}
fn main() {
use std::collections::{BTreeMap, HashMap};
{
let mut m = HashMap::new();
m.insert("a".to_string(), 0);
m.insert("key3".to_string(), 1);
edit_map_values(&mut m);
println!("{:#?}", m);
}
{
let mut m = BTreeMap::new();
m.insert("a".to_string(), 0);
m.insert("key3".to_string(), 1);
edit_map_values(&mut m);
println!("{:#?}", m);
}
}
Both times the output is the same, except for the order of the HashMap of course:
{
"a": 1,
"key2": 10,
"key3": 2,
}

Extend HashMap with contents of another HashMap [duplicate]

So I'm a bit stuck, trying to merge two HashMaps.
It's easy to do it inline:
fn inline() {
let mut first_context = HashMap::new();
first_context.insert("Hello", "World");
let mut second_context = HashMap::new();
second_context.insert("Hey", "There");
let mut new_context = HashMap::new();
for (key, value) in first_context.iter() {
new_context.insert(*key, *value);
}
for (key, value) in second_context.iter() {
new_context.insert(*key, *value);
}
println!("Inline:\t\t{}", new_context);
println!("Inline:\t\t{}\t{} [Initial Maps Still Usable]", first_context, second_context);
}
It's easy enough to make a function:
fn abstracted() {
fn merge<'a>(first_context: &HashMap<&'a str, &'a str>, second_context: &HashMap<&'a str, &'a str>) -> HashMap<&'a str, &'a str> {
let mut new_context = HashMap::new();
for (key, value) in first_context.iter() {
new_context.insert(*key, *value);
}
for (key, value) in second_context.iter() {
new_context.insert(*key, *value);
}
new_context
}
let mut first_context = HashMap::new();
first_context.insert("Hello", "World");
let mut second_context = HashMap::new();
second_context.insert("Hey", "There");
println!("Abstracted:\t{}", merge(&first_context, &second_context));
println!("Abstracted:\t{}\t{} [Initial Maps Still Usable]", first_context, second_context);
}
However, I can't seem to get the generic version to work:
fn generic() {
fn merge<'a, K: Hash + Eq, V>(first_context: &HashMap<&'a K, &'a V>, second_context: &HashMap<&'a K, &'a V>) -> HashMap<&'a K, &'a V> {
let mut new_context = HashMap::new();
for (key, value) in first_context.iter() {
new_context.insert(*key, *value);
}
for (key, value) in second_context.iter() {
new_context.insert(*key, *value);
}
new_context
}
let mut first_context = HashMap::new();
first_context.insert("Hello", "World");
let mut second_context = HashMap::new();
second_context.insert("Hey", "There");
println!("Generic:\t{}", merge(&first_context, &second_context));
println!("Generic:\t{}\t{} [Initial Maps Still Usable]", first_context, second_context);
}
The above code on play.rust-lang.org.
Compiling it:
error: the trait `core::kinds::Sized` is not implemented for the type `str`
I get that the compiler is confused about the size of the generic value, but I'm not sure why "str" doesn't have a strict memory size? I know its a String slice and not a type, but still this should work, no? Is this a bug?
I thought this would be a relatively trivial function. If someone has a good solution, I'd love to learn. Actually ideally, I'd love to see a solution with a trait Mergeable and write a decorator for HashMap<&K, &V>, such that I can call let new_context = first_context.merge(&second_context); but this can be a different question.
A more up to date answer from this tweet:
use std::collections::HashMap;
// Mutating one map
fn merge1(map1: &mut HashMap<(), ()>, map2: HashMap<(), ()>) {
map1.extend(map2);
}
// Without mutation
fn merge2(map1: HashMap<(), ()>, map2: HashMap<(), ()>) -> HashMap<(), ()> {
map1.into_iter().chain(map2).collect()
}
// If you only have a reference to the map to be merged in
fn merge_from_ref(map: &mut HashMap<(), ()>, map_ref: &HashMap<(), ()>) {
map.extend(map_ref.into_iter().map(|(k, v)| (k.clone(), v.clone())));
}
Rust Playground Link
This version does work:
use std::collections::HashMap;
use std::hash::Hash;
fn main() {
fn merge<K: Hash + Eq + Copy, V: Copy>(first_context: &HashMap<K, V>, second_context: &HashMap<K, V>) -> HashMap<K, V> {
let mut new_context = HashMap::new();
for (key, value) in first_context.iter() {
new_context.insert(*key, *value);
}
for (key, value) in second_context.iter() {
new_context.insert(*key, *value);
}
new_context
}
let mut first_context = HashMap::new();
first_context.insert("Hello", "World");
let mut second_context = HashMap::new();
second_context.insert("Hey", "There");
println!("Generic:\t{}", merge(&first_context, &second_context));
println!("Generic:\t{}\t{} [Initial Maps Still Usable]", first_context, second_context);
}
The difference is in the signature of merge(). Here is yours:
fn merge<'a, K: Hash + Eq, V>(first_context: &HashMap<&'a K, &'a V>, second_context: &HashMap<&'a K, &'a V>) -> HashMap<&'a K, &'a V>
Here is mine:
fn merge<K: Hash + Eq + Copy, V: Copy>(first_context: &HashMap<K, V>, second_context: &HashMap<K, V>) -> HashMap<K, V>
For some reason you are trying to abstract HashMap<&str, &str> to HashMap<&K, &V>, but this is not really correct: while &str is a borrowed pointer, it is special - it points to dynamically sized type str. Size of str is not known to the compiler, so you can use it only through a pointer. Consequently, neither Hash nor Eq are implemented for str, they are implemented for &str instead. Hence I've changed HashMap<&'a K, &'a V> to HashMap<K, V>.
The second problem is that in general you can't write your function if it takes only references to maps. Your non-generic merge function works only because &str is a reference and references are implicitly copyable. In general case, however, both keys and values can be non-copyable, and merging them into the single map will require moving these maps into the function. Adding Copy bound allows that.
You can also add Clone bound instead of Copy and use explicit clone() call:
fn merge<K: Hash + Eq + Clone, V: Clone>(first_context: &HashMap<K, V>, second_context: &HashMap<K, V>) -> HashMap<K, V> {
// ...
for (key, value) in first_context.iter() {
new_context.insert(key.clone(), value.clone());
}
// ...
}
The most general way, however, is moving maps into the function:
fn merge<K: Hash + Eq, V>(first_context: HashMap<K, V>, second_context: HashMap<K, V>) -> HashMap<K, V> {
// ...
for (key, value) in first_context.into_iter() {
new_context.insert(key, value);
}
// ...
}
Note into_iter() method which consumes the map, but returns an iterator of tuples with actual values instead of references.

Resources