我正在从头开始用 Rust 编写一个自上而下的解析器,这就是我到目前为止所拥有的。
use std::str::Chars;
struct Lexer<'a> {
peek: Option<char>,
chars: Chars<'a>,
}
impl<'a> Lexer<'a> {
fn new(string: &'a str) -> Self {
let mut chars = string.chars();
Self {
peek: chars.next(),
chars
}
}
fn next(&mut self) -> Option<char> {
let peek = self.peek;
self.peek = self.chars.next();
peek
}
fn peek(&self) -> Option<char> {
self.peek
}
fn next_if<F>(&mut self, cond: F) -> Option<char> where
F: FnOnce(char) -> bool {
if cond(self.peek()?) {
self.next()
} else {
None
}
}
fn eat_while<F>(&mut self, cond: F) where
F: FnOnce(char) -> bool {
while self.next_if(cond).is_some() {}
}
}
在这里你可以看到我的 eat_while 实现接受一个 lambda(称为 cond)并推进迭代器,直到指定的值与 cond 不匹配,或者 chars 迭代器为空。 因为 while 循环使迭代器前进,所以不需要循环体。然而,我被告知空 while 循环是不好的做法
我尝试的是在 eat_while 中重新创建“next_if”功能。
然而,这似乎是不可能的:
while cond(self.peek()).is_some()
// does not work
因为 self.peek() 返回一个选项,所以无法将其传递给 cond。
我尝试打开 self.peek():
while cond(self.peek().unwrap()).is_some()
// does not work
如果到达文件末尾,这会发生 panic ,所以它绝对不是一个选项。
最佳答案
在这种情况下,您可以使用Option::and_then
:
while self.peek().and_then(|p| cond(p)).is_some() {/*...*/}
关于rust - while 循环推进迭代器 - 这是好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74782509/