The compiler is referring to the value the match arm bodies return, not the type of the pattern of each match arm.
Some(count) => *count += 1,
None => map.insert(a, 0),
The expression *count += 1
evaluates to ()
(called "unit" in Rust, "void" in many other languages). The expression map.insert(a, 0)
on the other hand returns Option<V>
where V
is the value type of the hash map (an integer in your case). Suddenly the error message does make some sense:
= note: expected type `()`
= note: found type `std::option::Option<{integer}>`
I suppose you don't even want to return something from the match
block (remember: match
blocks are expressions, too, so you could return something from it). To discard the result of any expression, you can convert it to a statement with ;
. Let's try this:
match map.get(&a) {
Some(count) => {
*count += 1;
}
None => {
map.insert(a, 0);
}
}
Each match arm body is a block now (something between {
and }
) and each block contains one statement. Note that we technically don't need to change the first match arm, as *count += 1
already returns ()
, but this way it's more consistent.
But once you test this, another error related to borrowing will be shown. This is a well known issue and is explained in more detail here. In short: the borrow checker is not smart enough to recognize that your code is fine and therefore you should use the super nice entry
-API:
let map = HashMap::new();
map.insert("a", 0);
let a = "a";
*map.entry(&a).or_insert(0) += 1;
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…