繁体   English   中英

如何使用通用 rust 类型实现字典?

[英]How to implement a dictionary with generic rust types?

我一直在研究官方的 rust 书,在“闭包”一章中,有一个演示如何使用 rust 使用 structs 和 impl 来使用缓存,然后最后他们说我们在代码中添加了函数,其中一个开始使用字典以便我们可以拥有多个缓存,我很快就做到了,但后来它说:

当前 Cacher 实现的第二个问题是它只接受带有一个 u32 类型参数并返回 u32 的闭包。 例如,我们可能希望缓存采用字符串切片并返回 usize 值的闭包结果。 要解决此问题,请尝试引入更多通用参数以增加缓存功能的灵活性。

现在代码的相关部分,经过我的修改,它看起来像这样。

struct Cacher<T>
where
    T: Fn(u32) -> u32,
{
    calculation: T,
    value: HashMap<u32, u32>,
}

impl<T> Cacher<T>
where
    T: Fn(u32) -> u32,
{
    fn new(calculation: T) -> Cacher<T> {
        Cacher {
            calculation,
            value: HashMap::new(),
        }
    }

    fn value(&mut self, arg: u32) -> u32 {
        match self.value.get(&arg) {
            Some(n) => *n,
            None => {
                let v = (self.calculation)(arg);
                self.value.insert(arg, v);
                v
            },
        }
    }
}

尝试允许 HashMap 接收通用值,如下所示。

struct Cacher<T, K>
where
    T: Fn(K) -> K,
    HashMap<K, K>:  std::hash::Hash + std::cmp::Eq,
{
    calculation: T,
    value: HashMap<K, K>,
}

impl<T, K> Cacher<T, K>
where
    T: Fn(K) -> K,
    HashMap<K, K>: std::hash::Hash + std::cmp::Eq,
{
    fn new(calculation: T) -> Cacher<T, K> {
        Cacher {
            calculation,
            value: HashMap::new(),
        }
    }

    fn value(&mut self, arg: K) -> K {
        match self.value.get(&arg) {
            Some(n) => *n,
            None => {
                let v = (self.calculation)(arg);
                self.value.insert(arg, v);
                v
            },
        }
    }
}

我收到以下错误

error[E0599]: no method named `get` found for struct `HashMap<K, K>` in the current scope
  --> src/main.rs:27:26
   |
27 |         match self.value.get(&arg) {
   |                          ^^^ method not found in `HashMap<K, K>`
   |
   = note: the method `get` exists but the following trait bounds were not satisfied:
           `K: Eq`
           `K: Hash`

error[E0599]: no method named `insert` found for struct `HashMap<K, K>` in the current scope
  --> src/main.rs:31:28
   |
31 |                 self.value.insert(arg, v);
   |                            ^^^^^^ method not found in `HashMap<K, K>`
   |
   = note: the method `insert` exists but the following trait bounds were not satisfied:
           `K: Eq`
           `K: Hash`

error[E0277]: the trait bound `HashMap<_, _>: Hash` is not satisfied
  --> src/main.rs:39:33
   |
5  | struct Cacher<T, K>
   |        ------ required by a bound in this
...
8  |     HashMap<K, K>:  std::hash::Hash + std::cmp::Eq,
   |                     --------------- required by this bound in `Cacher`
...
39 |     let mut expensive_closure = Cacher::new(|num| {
   |                                 ^^^^^^^^^^^ the trait `Hash` is not implemented for `HashMap<_, _>`

error[E0599]: no function or associated item named `new` found for struct `Cacher<_, _>` in the current scope
   --> src/main.rs:39:41
    |
5   | / struct Cacher<T, K>
6   | | where
7   | |     T: Fn(K) -> K,
8   | |     HashMap<K, K>:  std::hash::Hash + std::cmp::Eq,
...   |
11  | |     value: HashMap<K, K>,
12  | | }
    | |_- function or associated item `new` not found for this
...
39  |       let mut expensive_closure = Cacher::new(|num| {
    |                                           ^^^ function or associated item not found in \`Cacher<_, _>\`
    | 
   ::: /home/fraco/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/collections/hash/map.rs:201:1
    |
201 |   pub struct HashMap<K, V, S = RandomState> {
    |   ----------------------------------------- doesn't satisfy `HashMap<_, _>: Hash`
    |
    = note: the method `new` exists but the following trait bounds were not satisfied:
            `HashMap<_, _>: Hash`

error: aborting due to 4 previous errors

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `functionall`

更新

我也执行了答案的建议,但现在我不知道如何使用以下代码启动 HashMap。

struct Cacher<T, K>                                                                                                       
where                                                                                                                     
   T: Fn(K) -> K,                                                                                                        
   K:  Hash + Eq,                                                                                                        
    {                                                                                                                         
        calculation: T,                                                                                                       
        value: HashMap<K,K>,                                                                                                  
    }                                                                                                                         
                                                                                                                             
impl<T, K> Cacher<T, K>                                                                                                   
where                                                                                                                     
        T: Fn(K) -> K,                                                                                                        
        K: Hash + Eq,                                                                                                         
    {                                                                                                                         
        fn new(calculation: T) -> Cacher<T, K> {                                                                              
            Cacher {                                                                                                          
                calculation,                                                                                                  
                value: HashMap::new(),                                                                                        
            }                                                                                                                 
        }            

错误

error[E0308]: mismatched types
  --> src/main.rs:24:20
   |
16 | impl<T, K> Cacher<T, K>
   |         - this type parameter
...
24 |             value: HashMap::new(),
   |                    ^^^^^^^^^^^^^^ expected type parameter `K`, found struct `HashMap`
   |
   = note: expected type parameter `K`
                      found struct `HashMap<_, _>`

error[E0599]: no method named `get` found for type parameter `K` in the current scope
  --> src/main.rs:29:26
   |
29 |         match self.value.get(&arg) {
   |                          ^^^ method not found in `K`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `get`, perhaps you need to restrict type parameter `K` with it:
   |
16 | impl<T, K: SliceIndex> Cacher<T, K>
   |         ^^^^^^^^^^^^^

error[E0599]: no method named `insert` found for type parameter `K` in the current scope
  --> src/main.rs:33:28
   |
33 |                 self.value.insert(arg, v);
   |                            ^^^^^^ method not found in `K`

error: aborting due to 3 previous errors

然后我尝试了很多不同的东西,但没有一个对我有用,我在谷歌搜索了一下,但没有找到我需要的东西,这就是为什么我来找你寻求帮助,知道如何实现代码。

PS:我很喜欢rust,我明白为什么最喜欢

错误信息

error[E0599]: no method named `get` found for struct `HashMap<K, K>` in the current scope
  --> src/main.rs:27:26
   |
27 |         match self.value.get(&arg) {
   |                          ^^^ method not found in `HashMap<K, K>`
   |
   = note: the method `get` exists but the following trait bounds were not satisfied:
           `K: Eq`
           `K: Hash`

告诉您HashMap<K,V>::get仅在 K 实现EqHash时存在。 但是您的value function 没有对 K 施加任何此类限制。(相反,您尝试将限制限制在Hash<K,K>上。只需在where子句中将它们添加到K就足够了:

impl<T, K> Cacher<T, K>
where
    T: Fn(K) -> K,
    K: std::hash::Hash + std::cmp::Eq
{

但是,这不足以让您的代码编译,您在 value 中所做的事情需要 K 是Copy - 这也需要添加到where子句中的限制中。 通常,您会尝试通过使用Clone代替或返回引用来减少该要求。

另外:如果您想要更通用的解决方案,您可能应该将其Cacher<T,K,V>并让T: Fn(K)->V

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM