我希望以“函数式编程”风格编写一些代码。
但是,我从一个结果的迭代器开始,我只想将函数应用于Ok
项。此外,我想在第一个错误停止迭代(不过,我可以接受不同的行为)。
目前,我正在使用嵌套的map()
模式:<iter>.map(|l| l.map(replace))
。我觉得这非常丑陋。
使用夜间版“result_flattening”,我可以将每个嵌套的Result<Result<T, E>, E>
扁平化为Result<T, E>
。使用eyre::Context
,我将不同的错误类型转换为eyre::Report
错误类型。所有这些都感觉非常笨拙。
有什么优雅的方法可以在Rust中编写这段代码?
最小工作示例
#![feature(result_flattening)]
use std::io::BufRead;
use eyre::Context;
fn main() {
let data = std::io::Cursor::new(b"FFBFFFBLLL\nBFBFBBFRLR\nFFFBFFBLLL");
let seats: Result<Vec<_>, _> = data
.lines()
.map(|l| l.map(replace).context("force eyre"))
.map(|l| l.map(|s| u32::from_str_radix(&s, 2).context("force eyre")))
.map(|r| r.flatten())
.collect();
println!("{:#?}", seats);
}
fn replace(line: String) -> String {
line.replace('F', "0")
.replace('B', "1")
.replace('L', "0")
.replace('R', "1")
}
更多参考资料:
- 如何在Iterator::map返回Result::Err时停止迭代并返回错误?
- Result实现
FromIter
。 result_flatten
:https://doc.rust-lang.org/std/result/enum.Result.html?search=#method.flatten,https://github.com/rust-lang/rust/issues/70142 (我正在使用的是rustc 1.49.0-nightly(ffa2e7ae8 2020-10-24))lines()
返回Result
: https://doc.rust-lang.org/std/io/trait.BufRead.html#method.lines