我需要一个迭代器来流式传输Read
. 这个迭代器:
[a-zA-Z]
我最终得到了以下实现(在这里测试):
fn get_first_words<'a>(r: &'a mut impl Read) -> impl Iterator<Item = Result<String>> + 'a {
BufReader::new(r).lines().filter_map(|rline| {
match rline.map(|line| {
line.split_whitespace()
.next()
.filter(|word| word.chars().all(char::is_alphabetic))
.map(&str::to_string)
}) {
Err(e) => Some(Err(e)),
Ok(Some(w)) => Some(Ok(w)),
Ok(None) => None,
}
})
}
这工作正常,但比我预期的要复杂。在这个实现中有嵌套的迭代器,为了Result
在过滤包含的值时保持包装类型,有一些类型杂耍。
这是否可以写得更简单,更少的嵌套逻辑和更少的类型杂耍?
你可以用 替换你的match
表达式Result::transpose()
。我还建议拆分返回第一个单词的函数,以使代码更具可读性。最后,你不需要接受&'a mut impl Read
——简单地接受impl Read
也可以,因为有一个实现for的转发实现。总之,简化的代码可能如下所示:Read
&mut impl Read
fn first_word(s: String) -> Option<String> {
s.split_whitespace()
.next()
.filter(|word| word.chars().all(char::is_alphabetic))
.map(From::from)
}
fn get_first_words(r: impl Read) -> impl Iterator<Item = Result<String>> {
BufReader::new(r)
.lines()
.filter_map(|line| line.map(first_word).transpose())
}
编辑:使用impl Read
而不是&mut impl Read
将导致可变引用被移动到函数中而不是被隐式重新借用,所以也许这毕竟不是一个好主意,因为记住在必要时显式重新借用它们会令人困惑。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句