STRING:
use std::collections::HashMap;
pub fn foo(strs: Vec<String>) -> i32 {
let (roots, ranks) : (HashMap<&String,&String>, HashMap<&String,i32>) = strs.iter().fold(
(HashMap::new(), HashMap::new()),
|(mut roots, mut ranks), s| {
roots.insert(s,s);
ranks.insert(s,1);
(roots, ranks)
}
);
0
}
GENERIC:
use std::collections::HashMap;
use std::slice::Iter;
//This is forcing me to learn rust's generics and fight with lifespans
struct UnionFind<T> {
roots: HashMap<T, T>,
ranks: HashMap<T, usize>,
len: usize
}
impl<T: std::cmp::Eq + std::hash::Hash + Copy> UnionFind<T> {
//Constructors
pub fn from_iter( v: Iter<T>) -> Self {
let ( roots, ranks ): (HashMap::<T,T>, HashMap::<T,usize>) = v.fold(
(HashMap::new(), HashMap::new()),
|(mut roots, mut ranks), **&**t| {
roots.insert(t,t);
ranks.insert(t,1 as usize);
(roots,ranks)
}
);
UnionFind {
len: roots.len(),
roots: roots,
ranks: ranks,
}
}
}
Hi,
I'm looking for some clarification on what appears to be inconsistent behavior with the accumulator function provided to a fold call, though I'm sure its my lack of understanding.
When calling fold on a Iterator of &String (see the first example above), it appears that the accumulator function provided to the fold call also takes the type &String, indicating that the value is passed to the accumulator function. This is what I expected.
My confusion occurs when I try to abstract out the fold call via generics. In this example (see the second example above) the only way I can get my code to compile is if I dereference the generic type T, indicating that &T is the type that is provided to the accumulator function provided to my fold call.
All in all, its not that big of a deal (I can get it to compile with one extra character), but it does indicate that I'm not understanding something that seems pretty fundamental. If someone could help me out and explain why the string call to fold does not act as a reference (ie &&String) but the generic does (ie &T) it would be greatly appreciated.
Thanks!