我试图让我了解Rust的类型系统。
use std::collections::HashSet;
fn hs_contains<T>(hs: &HashSet<T>, value: &T) -> bool
where
T: PartialEq,
{
hs.iter().any(|v| v == value)
}
fn main() {
// move strings into HashSet
let known_values: HashSet<&str> = ["a", "b", "c"].iter().cloned().collect();
// provided an Vec<String>
let provided_values: Vec<String> = vec!["a".to_string(), "b".to_string(), "z".to_string()];
// hash set of refrences
let mut found: HashSet<&str> = HashSet::new();
found.insert(&provided_values[0]);
found.insert(&provided_values[1]);
found.insert(&provided_values[2]);
let missing: HashSet<_> = known_values.difference(&found).collect();
let value: &String = &provided_values[1];
hs_contains(&known_values, value);
hs_contains(&missing, "c");
println!("missing: {:#?}", missing);
}
(Playground)
由于类型不强制,因此示例代码无法编译。是否可以提出
hs_contains
的类型声明,该声明将满足示例底部的条件:hs_contains(&known_values, value);
hs_contains(&missing, "c");
为什么我不只使用
HashSet::contains
?用
hs_contains
替换HashSet::contains
known_values.contains(value);
missing.contains(&"c");
导致以下编译错误
error[E0277]: the trait bound `&str: std::borrow::Borrow<std::string::String>` is not satisfied
--> src/main.rs:38:18
|
38 | known_values.contains(value);
| ^^^^^^^^ the trait `std::borrow::Borrow<std::string::String>` is not implemented for `&str`
我知道要完成这项工作的唯一其他方法是
known_values.iter().any(|v| v == value);
这激发了我对如何使用可以封装以上内容的类型声明定义函数的兴趣。
最佳答案
一个小的更改就可以使它编译:将&
从函数的声明移到函数的内部
fn hs_contains<T>(hs: &HashSet<T>, value: T) -> bool
where
T: std::cmp::PartialEq,
{
hs.iter().any(|v| v == &value)
}
并在
&
上添加一个"c"
hs_contains(&missing, &"c" );
(Playground)
现在为什么在函数内移动
&
有什么不同?正如Max在下面的评论中所解释的
When you use
<T>
and latervalue:T
you ask rust to figure out whatT
really is. In your case it should be a reference to astr
. When you use value&T
you now ask for a reference to a reference of astr
(a&&str
)
关于types - 我应该使用什么类型声明来创建自己的HashMap contains方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60709589/