У меня есть это чудовище вложенного кода в Rust, который отлично работает.
Идея состоит в том, чтобы открыть структуру данных локальной конфигурации репо git, если это возможно, в противном случае просто вернуть пустую GitConfig
. Существует ряд вызовов, которые необходимы для поиска текущего каталога, поиска в нем репо git, открытия репо, а затем открытия внутри него конфигурации, каждый из которых может выдать ошибку или вернуть None
. Мне все равно, какая ошибка выдается (или когда возвращается None
), за исключением того, что когда выдается ошибка (или возвращается None
), пустой GitConfig возвращается из всей цепочки .
let local = match env::current_dir() {
Err(_) => GitConfig::new().unwrap(),
Ok(cwd) => {
match find_git_root(&cwd) {
None => GitConfig::new().unwrap(),
Some(git_path) => {
match Repository::open(&git_path) {
Err(_) => GitConfig::new().unwrap(),
Ok(repo) => {
match repo.config() {
Err(_) => GitConfig::new().unwrap(),
Ok(config) => {
config.open_level(Local).unwrap()
}
}
}
}
}
}
}
};
Я пытаюсь преобразовать это в более функциональный стиль с использованием комбинаторов, таких как map()
and_then()
и других, но у меня переполняется стек в голове, пытаясь понять это вне. Я уверен, что есть способ сделать это, принимая во внимание типы возврата Result
и Options
в цепочке, а также тот факт, что конкретные типы Error
в пределах Result
отличаются от call to call.
Есть ли хороший, идиоматический c способ написать это функционально, передавая любую ошибку по цепочке, чтобы ее можно было обработать в самом конце с помощью ok_or_else()
или map_or_else()
или похожие? И как я могу сгладить вложение, чтобы код выглядел чище и было легче читать?