gpt4 book ai didi

error-handling - 如何返回包含结果迭代器的每个错误的结果,而不仅仅是第一个错误?

转载 作者:行者123 更新时间:2023-11-29 08:03:35 25 4
gpt4 key购买 nike

我正在尝试用 Rust 实现一个简单的解释器,为此我创建了一个 Tokens结构,它采用源字符并生成 TokenScanErrorResult 里面:

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 , 很容易将结果收集到第一个 ScanErrorToken 的矢量小号:

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都不是在我的箱子里是本地的。谁能建议一种干净的方法来做到这一点?

我已经使用 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())
}

最佳答案

unwrapping each Result

我会使用 itertools 的 partition_map避免需要解包:

use itertools::{Either, Itertools}; // 0.8.0

fn iterator() -> impl Iterator<Item = Result<i32, bool>> {
vec![Ok(1), Err(false), Ok(2), Err(true), Ok(3)].into_iter()
}

fn example() -> Result<Vec<i32>, Vec<bool>> {
let (values, errors): (Vec<_>, Vec<_>) = iterator().partition_map(|v| match v {
Ok(v) => Either::Left(v),
Err(e) => Either::Right(e),
});

if errors.is_empty() {
Ok(values)
} else {
Err(errors)
}
}

另见:

您还可以使用 OptionResult 实现 IntoIterator 的事实来避免确切的 unwrap,尽管这仍然处理一个集合两次:

fn example2() -> Result<Vec<i32>, Vec<bool>> {
let (values, errors): (Vec<_>, Vec<_>) = iterator().partition(|result| result.is_ok());

if errors.is_empty() {
Ok(values.into_iter().flat_map(Result::ok).collect())
} else {
Err(errors.into_iter().flat_map(Result::err).collect())
}
}

另见:

关于error-handling - 如何返回包含结果迭代器的每个错误的结果,而不仅仅是第一个错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55102253/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com