generics - 通用高阶函数引用错误

标签 generics rust higher-order-functions

我整晚都在为这个问题苦苦思索。我正在尝试实现一个 to_hash_map 方法,这样我就可以:

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)
}

并希望得到 HashMap

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

这是我最好的尝试:

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);

我觉得我很亲近。任何帮助表示赞赏:)

最佳答案

你们确实很亲近。

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

您可以改变闭包的类型以获取 &&Person 或使用 into_iter 消耗向量 a

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

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

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"}

正如预期的那样。

关于generics - 通用高阶函数引用错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34739291/

相关文章:

快速检查对象类型

generics - 均值函数的 Rust 泛型语法

c# - 反序列化为通用排序列表 C#

typescript - 如何创建每个值的类型取决于键的查找?

scala - Scala 中的柯里化(Currying)与匿名函数

racket - 为什么 `filter` 使用高阶出现类型?

function - 在 Clojure 中传递带有参数作为参数的函数

initialization - 如何初始化包含引用的结构?

rust - 无法分配给 `x`,因为它是借用的

arrays - 如何为大于 32 的数组实现 serde::Deserialize?