gpt4 book ai didi

rust - 在 Rust 中调用结果迭代器上的映射

转载 作者:行者123 更新时间:2023-12-03 11:29:36 24 4
gpt4 key购买 nike

我想以“函数式编程”风格编写一些代码。
但是,我从结果迭代器开始,我只想将该函数应用于 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")
}
进一步引用:
  • How do I stop iteration and return an error when Iterator::map returns a Result::Err?
  • 结果实现 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 (ffa2e7ae8 2020-10-24))
  • lines()返回 Result s:https://doc.rust-lang.org/std/io/trait.BufRead.html#method.lines
  • 最佳答案

    由于您无论如何都会丢弃错误类型,因此您可以避免 eyre完全和使用 .ok转换 ResultOption ,然后只需使用 Optionand_then避免每次都变平:

    let seats: Option<Vec<_>> = data
    .lines()
    .map(|l| l.ok())
    .map(|l| l.map(replace))
    .map(|l| l.and_then(|s| u32::from_str_radix(&s, 2).ok()))
    // if you want to keep chaining
    .map(|l| l.and_then(|s| some_result_function(&s).ok()))
    .collect();
    如果您只想跳过错误,可以使用 filter_map 提供更优雅的解决方案。 :
    let seats: Vec<_> = data
    .lines()
    .filter_map(|l| l.ok())
    .map(replace)
    .filter_map(|l| u32::from_str_radix(&l, 2).ok())
    .collect();
    如果要维护错误,请将错误装入 Box<dyn Error>考虑不同类型:
    use std::error::Error;
    // later in the code
    let seats: Result<Vec<_>, Box<dyn Error>> = data
    .lines()
    .map(|x| x.map_err(|e| Box::new(e) as _))
    .map(|l| l.map(replace))
    .map(|l| l.and_then(|s| u32::from_str_radix(&s, 2).map_err(|e| Box::new(e) as _)))
    .collect();
    如果您不喜欢重复的 .map_err(|e| Box::new(e) as _) ,然后为它创建一个特征:
    use std::error::Error;

    trait BoxErr {
    type Boxed;
    fn box_err(self) -> Self::Boxed;
    }

    impl<T, E: Error + 'static> BoxErr for Result<T, E> {
    type Boxed = Result<T, Box<dyn Error>>;

    fn box_err(self) -> Self::Boxed {
    self.map_err(|x| Box::new(x) as Box<dyn Error>)
    }
    }

    // later in the code

    let seats: Result<Vec<_>, Box<dyn Error>> = data
    .lines()
    .map(|x| x.box_err())
    .map(|l| l.map(replace))
    .map(|l| l.and_then(|s| u32::from_str_radix(&s, 2).box_err()))
    .collect();

    关于rust - 在 Rust 中调用结果迭代器上的映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65154816/

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