I'm not really sure how to write a high-order function that wants to return an error of its own and make it look nice when I use it on another functions that also return a Result.
This is hard to describe. Here's an example:
use std::fs;
use std::io;
use std::io::Read;
use std::fmt;
use std::error::Error;
#[derive(Debug)]
struct MyError;
impl Error for MyError {}
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "MyError")
}
}
fn log_something() -> Result<(), MyError> {
unimplemented!()
}
fn log_and_call<T>(f: &dyn Fn() -> T) -> Result<T, MyError> {
log_something()?;
Ok(f())
}
fn the_answer() -> i32 {
42
}
fn read_username_from_file() -> Result<String, io::Error> {
let mut f = fs::File::open("hello.txt")?;
let mut s = String::new();
f.read_to_string(&mut s)?;
Ok(s)
}
fn main() {
let _logged_answer: Result<i32, MyError> = log_and_call(&the_answer);
let _logged_username: Result<Result<String, io::Error>, MyError> = log_and_call(&read_username_from_file);
}
How do I avoid having that Result<Result<String, io::Error>, MyError> there? I'd like to have Result<String, Error>, or maybe something even more sensible.
Maybe there's a more idomatic way to do this?