我正在尝试在Rust中实现一个简单的解释器,为此我创建了一个Tokens
结构体,它接收源代码字符并产生一个Token
或ScanError
,存储在Result
中:
pub struct Tokens<'src> {
chars: Chars<'src>,
}
impl<'src> Iterator for Tokens<'src> {
type Item = Result<Token, ScanError>;
fn next(&mut self) -> Option<Result<Token, ScanError>> {
// ...
}
}
由于 Result
实现了 FromIterator
,因此可以将结果简单地收集到第一个 ScanError
或一个 Token
向量中:
fn scan_tokens(source: &str) -> Result<Vec<Token>, ScanError> {
let iter = Tokens {
chars: source.chars(),
};
iter.collect()
}
在出现多个错误的情况下,我真的希望返回每一个错误:
fn scan_tokens(source: &str) -> Result<Vec<Token>, Vec<ScanError>> {
// what goes here?
}
据我所知,由于
FromIterator
特征或 Result
不在我的crate中,因此我不可能实现自己的版本。 有人能提供一种干净的方法吗?我已经编写了一个使用迭代器上的
partition 实现的代码,然后解开每个 Result ,但是这不好阅读,感觉没有充分利用迭代器。
type T = Vec<Result<Token, ScanError>>;
fn scan_tokens(source: &str) -> Result<Vec<Token>, Vec<ScanError>> {
let iter = Tokens {
chars: source.chars(),
};
let (tokens_results, error_results): (T, T) = iter.partition(|result| result.is_ok());
let errors: Vec<ScanError> = error_results
.into_iter()
.map(|result| result.unwrap_err())
.collect();
if errors.len() > 0 {
return Err(errors);
}
Ok(tokens_results
.into_iter()
.map(|result| result.unwrap())
.collect())
}