Я хотел бы написать код в стиле функционального программирования.
Однако я начинаю с итератора результатов и хочу применить эту функцию только к Ok
элементам. Кроме того, я хочу остановить итерацию при первой ошибке (однако я был бы открыт для другого поведения).
Пока что я использую вложенный шаблон map()
: <iter>.map(|l| l.map(replace))
. Я считаю это крайне некрасивым.
Используя nightly 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?
- Результат реализует
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
s: https://doc.rust-lang.org/std/io/trait.BufRead.html#method.lines