通用高阶函数引用错误

时间:2016-01-12 09:01:50

标签: generics rust higher-order-functions

我整晚都在抨击这个人。我正在尝试实现struct Person { id: i32, first_name: &'static str, } fn main() { let brad = Person { id: 1, first_name: "brad", }; let barb = Person { id: 2, first_name: "Barb", }; let a = vec![brad, barb]; let key_func = |i: &Person| -> i32 { i.id }; let value_func = |i: &Person| -> &str { i.first_name }; let map = a.iter().to_hash_map(key_func, value_func); println!("{:?}", map) } 方法,以便我可以这样做:

{
 1: "brad",
 2: "barb"
}

并希望获得HashMap

trait ToHashMap<T,K,V, FK, FV>
    where K:Hash,
          K:Eq,
          FK:Fn(&T)->K,
          FV:Fn(&T)->V {

    fn to_hash_map(&self, key_func: FK, value_func: FV) -> HashMap<K, V>;
}

impl<T, K, V, FK, FV, I> ToHashMap<T, K, V, FK, FV> for I
    where K: Hash,
          K: Eq,
          FK: Fn(&T) -> K,
          FV: Fn(&T) -> V,
          I: Iterator<Item = T>
{
    fn to_hash_map(&self, key_func: FK, value_func: FV) -> HashMap<K, V>{
        let mut hm: HashMap<K, V> = HashMap::new();
        loop {
            match self.next() {
                Some(x) => {
                    hm.insert(key_func(&x), value_func(&x));
                }
                None => break,
            }
        }
        hm
    }
}

这是我最好的镜头:

error: type mismatch: the type `[closure@src/main.rs:92:20: 92:48]` implements the trait `for<'r> core::ops::Fn<(&'r Person,)>`, but the trait `for<'r> core::ops::Fn<(&'r &Person,
)>` is required (expected &-ptr, found struct `Person`) [E0281]
src/main.rs:94     let map = a.iter().to_hash_map(key_func, value_func);

但是我收到了错误:

GetDayOfYear

我觉得我太近了。任何帮助表示赞赏:)

2 个答案:

答案 0 :(得分:4)

你确实很亲密。

您面临的第一个问题是,iter()生成的Iterator::Item类型为&Person,因此您传递给关闭的&x类型为&&Person

您可以更改闭包的类型以使用&&Person,也可以使用a使用向量into_iter

我遇到的另一个小问题是你不能通过不可变引用来获取迭代器:你需要修改迭代器迭代。按值获取迭代器更简单。

总而言之,通过我们可以得到的两个调整(使用向量):

trait ToHashMap<T, K, V, FK, FV>
    where K: Hash,
          K: Eq,
          FK: Fn(&T)->K,
          FV: Fn(&T)->V {

    fn to_hash_map(self, key_func: FK, value_func: FV) -> HashMap<K, V>;
}

impl<T, K, V, FK, FV, I> ToHashMap<T, K, V, FK, FV> for I
    where K: Hash,
          K: Eq,
          FK: Fn(&T) -> K,
          FV: Fn(&T) -> V,
          I: Iterator<Item = T>
{
    fn to_hash_map(self, key_func: FK, value_func: FV) -> HashMap<K, V> {
        let mut hm: HashMap<K, V> = HashMap::new();
        for x in self {
            hm.insert(key_func(&x), value_func(&x));
        }
        hm
    }
}

然后it compiles and runs生成:

{2: "Barb", 1: "brad"}

正如所料。

答案 1 :(得分:0)

问题是a.iter()返回一个项目为&Person的迭代器。您的特征限制为ToHashMap impl要求键和值函数采用&T,其中T = ItemT = &Person,因此函数参数为{{1} },它与你的功能不匹配。

你必须以某种方式放松界限,虽然我担心我的Rust知识不足以说明确切的方式。