我是新的生 rust 和来掌握如何所有权和借用检查工程
我写了一个小函数
pub fn count_words(file_path: &str) -> Result<usize, Error> {
return File::open(file_path).map(|file| {
let reader = BufReader::new(file);
return reader
.lines()
.map(|line| line.unwrap())
.flat_map(|line| line.split_whitespace())
.count();
});
}
我得到这个错误
error[E0515]: cannot return value referencing function parameter `line`
--> src/lib.rs:19:30
|
19 | .flat_map(|line| line.split_whitespace())
| ----^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `line` is borrowed here
|
= help: use `.collect()` to allocate the iterator
我不确定我是否理解了这里发生的事情(因为哪个实体正在借用行,所以我不能调用分割空白)。
我设法让这个版本运行
pub fn count_words(file_path: &str) -> Result<usize, io::Error> {
return File::open(file_path).map(|file| {
let reader = BufReader::new(file);
let lines = reader.lines();
let mut num_words = 0;
for line in lines {
num_words += line.unwrap().split_whitespace().count();
}
return num_words
});
}
2条答案
按热度按时间jaql4c8m1#
Rust在这里遇到了麻烦,因为它创建了对
line
的短期引用,而这些引用必须在变量定义的范围之外持久化。既然你真的不关心行的内容,那么直接使用count就可以了:
在这里你可以很容易地把所有这些分裂的计数加起来。这大概就是您在更详细版本中所做的,但我认为这种代码在其Rust-ness方面读起来更好。
这里很明显,您可以通过将两个
map()
操作合并为一个来进一步减少代码量。yk9xbfzb2#
这个问题是由于
.split_whitespace()
返回一个迭代器,它将在每次迭代时refer到line
,但是line
,它是一个拥有的String
,一旦闭包返回,就会被删除。在
line
仍然存在的情况下,需要消耗这个迭代器的每次迭代。这里是另一个公式,仍然具有函数式风格(而不是显式循环)。请注意,我在
.map_while()
中用.unwrap()
交换了.ok()
,以避免在无法检索行时出现panic!()
。(虽然没有任何评论,但我猜这是对我之前尝试中未触发的Clippy lint的暗示。