I have been studying the official rust book, in the chapter on "closures" there is a demonstration of how to use cache with rust using structs and impl, then at the end they say that we add functions to the code, one of them start to use a dictionary so that we can have a multiple cache, I did that quickly, but then it says:
The second problem with the current Cacher implementation is that it only accepts closures that take one parameter of type u32 and return a u32. We might want to cache the results of closures that take a string slice and return usize values, for example. To fix this issue, try introducing more generic parameters to increase the flexibility of the Cacher functionality.
the relevant part of the code right now, with my modifications it looks like this.
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
},
}
}
}
try to allow the HashMap to receive generic values as follows.
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
},
}
}
}
I got the following error
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`
UPDATE
I also carried out the recommendations of an answer but now I don't know how to start the HashMap with the following code.
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
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
Then I tried many different things and none of them worked for me, I searched a little in google but I did not find what I need, that's why I come to you to ask for help, to know how to implement what is asked in the code.
P.S: I really like rust, I understand why it is the most loved