3 ms·
On that point, does that mean Rust libraries tend to have logging hooks or are all errors emitted by Result's? What about non-fatal errors such as retries in a
by cryptarch 9y ago
On that point, does that mean Rust libraries tend to have logging hooks or are all errors emitted by Result's?
What about non-fatal errors such as retries in a GUI library that loads an image from the web, how are they logged or otherwise propogated to the developer?
- burntsushi 9y agoErrors in Rust are just normal values, so there's nothing special you have to do. You just write your retry logic, presumably after inspecting the kind of error that occurred.
- cryptarch 9y agoI'm aware of how Result works, I've written a little Rust. I was wondering how Rust libraries specifically deal with non-fatal error handling in parts of the library that are abstracted away from the library consumer, such as my example of a GUI library that has retry behavior that is not exposed to the user. Is there currently a convention for dealing with such "encapsulated but interesting" errors occuring in Rust libraries? It seems obvious to me that a web framework would have a logging hook but non-obvious how that API would function; would it call a logging callback with a severity and a string? Just a string? Or an error message and some kind of "related data" (such as a stack trace or relevant structs) container? It doesn't seem obvious to me to log only text in the context of a GUI library. I'm thinking of building a native cross-platform GUI library in Rust (borrowing concepts from IUP[0] but adding more typing) and I feel like there would be value in having structured data as part of the nonfatal error interface, so I'm curious if there are existing patterns to learn from. [0] http://webserver2.tecgraf.puc-rio.br/iup/ http://webserver2.tecgraf.puc-rio.br/iup/
- burntsushi 9y agoAh, I see. For logging, the `log` crate[1] provides the interface that libraries can use, which defines macros for each log level. For partial success/failure, I actually don't think there is much convention. On the one hand, you might consider logging as sufficient enough, depending on your use case. In some cases, I have adopted a form of partial errors. That is, instead of: fn foobar() -> Result<Value, Error> { ... } I use fn foobar() -> (Value, Option<Error>) { ... } You can see an example here: https://docs.rs/ignore/0.1.9/ignore/gitignore/struct.Gitignore.html#method.new https://docs.rs/ignore/0.1.9/ignore/gitignore/struct.Gitigno... And in particular, the error type is a recursive structure, which permits it to store an aggregation of errors: https://docs.rs/ignore/0.1.9/ignore/enum.Error.html https://docs.rs/ignore/0.1.9/ignore/enum.Error.html Since this isn't something people need too often, the syntactic overhead of this approach is considerably clunkier, so I definitely wouldn't want this to be a pervasive part of a library. Nevertheless, if you can get both a success value and an error value, then your return type is inherently a product, not a sum, which is at odds with the `Result` sum. [1] - https://docs.rs/log/0.3.7/log/ https://docs.rs/log/0.3.7/log/