我对Rust很陌生,无法理解这个令人困惑的错误。
我只是想匹配Option
get
函数返回的HashMap
。如果返回一个值,我想增加它,如果不是,我想在地图上添加一个新元素。
以下是代码:
let mut map = HashMap::new();
map.insert("a", 0);
let a = "a";
match map.get(&a) {
Some(count) => *count += 1,
None => map.insert(a, 0),
}
产生的错误:
error[E0308]: match arms have incompatible types
--> <anon>:7:5
|
7 | match map.get(&a) {
| _____^ starting here...
8 | | Some(count) => *count += 1,
9 | | None => map.insert(a, 0),
10 | | }
| |_____^ ...ending here: expected (), found enum `std::option::Option`
|
= note: expected type `()`
found type `std::option::Option<{integer}>`
note: match arm with an incompatible type
--> <anon>:9:17
|
9 | None => map.insert(a, 0),
| ^^^^^^^^^^^^^^^^
我不确定编译器在这里抱怨什么类型,因为Some
和None
都是同一个枚举类型的一部分。任何人都可以解释编译器对我的代码有什么问题吗?
答案 0 :(得分:3)
编译器指的是匹配臂体返回的值,而不是每个匹配臂的模式类型。
Some(count) => *count += 1,
None => map.insert(a, 0),
表达式*count += 1
的计算结果为()
(称为&#34;单位&#34;在Rust中,&#34; void&#34;在许多其他语言中)。另一方面,表达式map.insert(a, 0)
返回Option<V>
,其中V
是哈希映射的值类型(在您的情况下为整数)。突然,错误消息确实有道理:
= note: expected type `()`
= note: found type `std::option::Option<{integer}>`
我想你甚至不想从match
块中返回一些东西(记住:match
块也是表达式,所以你可以从中返回一些东西)。要丢弃任何表达式的结果,可以将其转换为;
的语句。让我们试试这个:
match map.get(&a) {
Some(count) => {
*count += 1;
}
None => {
map.insert(a, 0);
}
}
现在每个匹配臂体都是一个块({
和}
之间的某个块),每个块包含一个语句。请注意,我们在技术上并不需要更改第一个匹配组,因为*count += 1
已经返回()
,但这样更加一致。
但是一旦你测试了这个,就会显示另一个与借用有关的错误。这是一个众所周知的问题,将更详细地解释here。简而言之:借用检查器不够智能,无法识别您的代码是正常的,因此您应该使用超级好entry
-API:
let map = HashMap::new();
map.insert("a", 0);
let a = "a";
*map.entry(&a).or_insert(0) += 1;