Ответ 1
Тип &(&str, &str)
происходит от того, что iter()
возвращает Vec
:
fn iter(&self) -> Iter<T>
где Iter<T>
реализует Iterator<Item=&T>
:
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T
...
}
Другими словами, iter()
на векторе возвращает итератор, дающий ссылки в вектор.
cloned()
решает проблему, потому что это адаптер итератора, который преобразует Iterator<Item=&T>
в Iterator<Item=T>
, если T
является клонируемым. Вы можете думать об этом как сокращение для 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);
Бывает, что (&str, &str)
является клонированным, потому что каждый компонент tuple также является клонированным (все ссылки есть), поэтому cloned()
возвращает объект, который реализует Iterator<Item=(&str, &str)>
- именно то, что collect()
необходимо создать HashMap
.
В качестве альтернативы вы можете использовать into_iter()
для получения Iterator<Item=T>
из Vec<T>
, но тогда будет использован исходный вектор:
use std::collections::HashMap;
fn main() {
let pairs = vec!(("foo", "bar"), ("toto", "tata"));
let map: HashMap<&str, &str> = pairs.into_iter().collect();
println!("{:?}", map);
}