插入HashMap<& str,u64>时出现类型不匹配错误

时间:2016-01-23 15:07:43

标签: rust

我正在创建一个简单的程序,它一次读取stdin一行直到它到达文件的末尾,然后在输入中打印每个字母的频率(即:字符,实际上是技术上的Unicode字母)。 The full source is on Github。我使用的是rustc版本1.6.0和货物0.7.0

在程序中,我定义了一个HashMap<&str, u64>来存储统计信息,使用字母作为键,并将该字母的出现次数作为值。循环遍历每个字母时,我会执行以下操作来存储统计信息:

for line in stdin.lock().lines() {
    let mut line = line.unwrap().as_str();

    // For each line, store it's character.
    for grapheme in UnicodeSegmentation::graphemes(line, true) {
        match counter.get(grapheme) {
            Some(v) => counter.insert(grapheme, v + 1),
            None => counter.insert(grapheme, 1)
        }
    }
}

grapheme is a reference to a string)。

我意识到这可能不是更新hashmap中计数器的最佳方法,但我相信它应该在技术上有效 - 毕竟我是一个完整的Rust n00b。

当我cargo build时,我得到:

 expected `()`,
    found `core::option::Option<u64>`
(expected (),
    found enum `core::option::Option`) [E0308]
src/main.rs:18             match counter.get(grapheme) {
src/main.rs:19                 Some(v) => counter.insert(grapheme, v + 1),
src/main.rs:20                 None => counter.insert(grapheme, 1)
src/main.rs:21             }

...从查看E0308的文档,以及确切的错误消息,我理解编译器正在获得一种类型并期待另一种类型;但我不明白:

  • 我是否看到两个不匹配或一个,即:
    • core::option::Option<u64>core::option::Option之间是否存在不匹配?
    • ()core::option::Option<u64>之间以及()core::option::Option之间是否有两个不匹配?
    • 别的什么?
  • 我不明白如何告诉Rust编译器如何解释具有正确类型的东西(即:如何解决问题)。

2 个答案:

答案 0 :(得分:4)

这就是说表达式返回Option<u64>,其中()(单位值,实际上“没有”)是预期的。

应该返回单位值的表达式是match。封闭的for返回()(即期望没有值返回),因此match预计也不返回任何值。但它的两个分支返回insert的结果Option

告诉Rust放弃返回值的方法是添加;,就像这样;

match counter.get(grapheme) {
    Some(v) => counter.insert(grapheme, v + 1),
    None => counter.insert(grapheme, 1)
}; //add a ; here

错误消息的格式为expected X, found Y (expected A, found B)XY是完全不匹配的类型,然后,在括号中,AB关注的是第一个不匹配出现的类型部分。当涉及泛型的类型不匹配时,这尤其有用。这是一个(人为的)例子:

use std::sync::{Arc, Mutex};

fn type_mismatch(x: Arc<Mutex<String>>) {}

fn main() {
    let a = Arc::new(Mutex::new(0i32));
    type_mismatch(a);
}

这会出现以下错误:

<anon>:7:19: 7:20 error: mismatched types:
 expected `alloc::arc::Arc<std::sync::mutex::Mutex<collections::string::String>>`,
    found `alloc::arc::Arc<std::sync::mutex::Mutex<i32>>`
(expected struct `collections::string::String`,
    found i32) [E0308]
<anon>:7     type_mismatch(a);
                           ^

此处,a变量的类型与xtype_mismatch参数的类型不匹配。请注意它们的类型是如何相似的,但两种情况下的区别在于Mutex的类型参数。编译器专注于这种差异,因此您可以更轻松地发现它。

随着您对所使用的库越来越熟悉,有时只需阅读有针对性的类型就足以帮助您找出问题所在。

答案 1 :(得分:3)

使用上面的代码,match表达式的类型为Option<u64>(因为所有分支的类型都为Option<u64>)。 for循环体必须以语句终止,因此只需添加;即可使match成为一个语句。

match counter.get(grapheme) {
    Some(v) => counter.insert(grapheme, v + 1),
    None => counter.insert(grapheme, 1)
};

Look here for more details