3 ms·
A framing about the problem I don't often see is: when do you want to throw away information about an error case? Losing that information is sometimes the right
by dwattttt 1y ago
A framing about the problem I don't often see is: when do you want to throw away information about an error case? Losing that information is sometimes the right thing to do (as you said, maybe you don't care about which file isn't found by a function, so you only use one error to represent the two times it can happen).
Maybe it would make sense to consider the API a function is presenting when making errors for it; if an error is related to an implementation detail, maybe it doesn't belong in the public API. If an error does relate to the public function's purpose (FileNotFound for a function that reads config), then it has a place there.
- fwip 1y agoI agree, it's tough to know when the right time to toss information away is, to simplify things for the caller. When in doubt, I tend to prefer "wrapper style" errors for libraries, so the caller can match at whatever level of specificity they care about. As a toy example: match read_config() { Err(ConfigError(FileNotFound) => println!("No configuration file found. Supported config directories are: {}", get_config_dirs()), Err(ConfigError(IOError(filename, msg))) => println!("Access error for config file {}: {}", filename, msg), Err(ConfigError(ParseError(e))) => println!("Parse error: {:?}", e), Err(ConfigError(e)) => println!("configuration error: {:?}", e), Ok(config) => {...}, } The calling application could start with just the generic error message at the end, and over time decide to add more useful behavior for some specific cases. Of course, then the problem becomes "what are the useful or natural groupings" for the error messages.
- dwattttt 1y agoI did this with a moderate sized cli tool; it was really good to be able to see effectively every error state you could have at the top level of the program. Something I didn't find an ergonomic solution to though was pulling out common errors; I wanted to say, pull out any std::io errors that occurred at the top level, but all I found was to match and expand every error case to pull them out. I considered maybe a derive/trait based approach would work, but it was too big a hammer for that project.