我正在创建一个简单的程序,它一次读取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
之间是否有两个不匹配?答案 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)
。 X
和Y
是完全不匹配的类型,然后,在括号中,A
和B
关注的是第一个不匹配出现的类型部分。当涉及泛型的类型不匹配时,这尤其有用。这是一个(人为的)例子:
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
变量的类型与x
上type_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)
};