The type &(&str, &str)
comes from what iter()
on a Vec
returns:
fn iter(&self) -> Iter<T>
where Iter<T>
implements Iterator<Item=&T>
:
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T
...
}
In other words, iter()
on a vector returns an iterator yielding references into the vector.
cloned()
solves the problem because it is an iterator adapter which converts Iterator<Item=&T>
to Iterator<Item=T>
if T
is cloneable. You can think of it as a shorthand for map(|v| v.clone())
:
let v1: Vec<i32> = vec![1, 2, 3, 4];
let v2: Vec<_> = v1.iter().cloned().collect();
let v3: Vec<_> = v1.iter().map(|v| v.clone()).collect();
assert_eq!(v2, v3);
It happens that (&str, &str)
is cloneable because each tuple component is also cloneable (all references are), so cloned()
would return an object which implements Iterator<Item=(&str, &str)>
- exactly what collect()
needs to create a HashMap
.
Alternatively, you can use into_iter()
to get Iterator<Item=T>
from Vec<T>
, but then the original vector will be consumed:
use std::collections::HashMap;
fn main() {
let pairs = vec!(("foo", "bar"), ("toto", "tata"));
let map: HashMap<&str, &str> = pairs.into_iter().collect();
println!("{:?}", map);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…