如何实现具有通用 rust 类型的字典?
How to implement a dictionary with generic rust types?
我一直在研究官方的rust书,在“闭包”一章中有演示如何使用structs和impl使用rust进行缓存,最后他们说我们在代码中添加功能,其中一个开始使用字典,这样我们就可以拥有多个缓存,我很快就做到了,但随后它说:
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.
现在代码的相关部分,经过我的修改,它看起来像这样。
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
然后我尝试了很多不同的东西,其中 none 对我有用,我在 google 中搜索了一下,但没有找到我需要的东西,这就是为什么我来找你问寻求帮助,了解如何实现代码中要求的内容。
P.S:我很喜欢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`
告诉你只有当K实现了Eq
和Hash
时HashMap<K,V>::get
才存在。
但是您的 value
函数没有对 K 施加任何此类限制。(相反,您尝试将限制限制在 Hash<K,K>
上。只需将它们添加到 K
中就足够了where
子句:
impl<T, K> Cacher<T, K>
where
T: Fn(K) -> K,
K: std::hash::Hash + std::cmp::Eq
{
虽然这不足以让您的代码编译,但您在内部所做的事情 value 要求 K 为 Copy
- 这也需要添加到 [=18 中的限制中=] 子句。通常,您会尝试通过使用 Clone
或返回引用来减少该要求。
旁白:如果您想要更通用的解决方案,您可能应该将其设为 Cacher<T,K,V>
并设为 T: Fn(K)->V
。
我一直在研究官方的rust书,在“闭包”一章中有演示如何使用structs和impl使用rust进行缓存,最后他们说我们在代码中添加功能,其中一个开始使用字典,这样我们就可以拥有多个缓存,我很快就做到了,但随后它说:
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.
现在代码的相关部分,经过我的修改,它看起来像这样。
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
然后我尝试了很多不同的东西,其中 none 对我有用,我在 google 中搜索了一下,但没有找到我需要的东西,这就是为什么我来找你问寻求帮助,了解如何实现代码中要求的内容。
P.S:我很喜欢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`
告诉你只有当K实现了Eq
和Hash
时HashMap<K,V>::get
才存在。
但是您的 value
函数没有对 K 施加任何此类限制。(相反,您尝试将限制限制在 Hash<K,K>
上。只需将它们添加到 K
中就足够了where
子句:
impl<T, K> Cacher<T, K>
where
T: Fn(K) -> K,
K: std::hash::Hash + std::cmp::Eq
{
虽然这不足以让您的代码编译,但您在内部所做的事情 value 要求 K 为 Copy
- 这也需要添加到 [=18 中的限制中=] 子句。通常,您会尝试通过使用 Clone
或返回引用来减少该要求。
旁白:如果您想要更通用的解决方案,您可能应该将其设为 Cacher<T,K,V>
并设为 T: Fn(K)->V
。