7 ms·
When I moved to Rust the constant error wrapping or converting annoyed me. But after using it for a couple of years it turned out to be a huge blessing. Quite o
by pat2man 7y ago
When I moved to Rust the constant error wrapping or converting annoyed me. But after using it for a couple of years it turned out to be a huge blessing. Quite often I need to know exactly which error messages will be thrown so that I can do things like internationalization. While exceptions are quite convenient for prototyping for production I’m now firmly in the typed errors camp.
- shadowgovt 7y agoAgreed. I nowadays consider code that might throw any type of exception to be inherently unsafe code; if you don't know what can go wrong, how do you have any idea whether you've addressed all reasonable failure modes?
- shepmaster 7y agoIt's not clear if you are continuing to refer to Rust as your parent post did, but if so, note that this is not the standard Rust meaning for "unsafe". Using it in such a way makes it more complicated to discuss and explain the Rust-specific meaning.
- shadowgovt 7y agoThank you for the clarification; I was using 'unsafe' colloquially and not in the Rust sense.
- ferzul 7y agoIf Rust devs took an everyday English word and gave it a different meaning, isn't it their fault when they have to train everyone into discarding their intuitions? It sounds like it means “code that is unsafe for a particular reason”; name the reason and leave developers capable of criticising code that is unsafe for other reasons, too. Unchecked Exception throwing code and stringly typed code are both unsafe. The world is better if we can call spades spades, instead of pitchfork style digging implements, because you want to protect playing card manufacturers.
- shepmaster 7y ago> If Rust devs took an everyday English word and gave it a different meaning Perhaps, but if we had come up with a new word, you or someone else would complain that we had done that instead of using a word that people already "understood". :-) English is a language full of elision, and there's nothing inherently wrong with using one word for closely related meanings. When being precise, Rust uses the term "memory unsafety", but we humans usually shorten that to just "unsafety" because we are lazy. My point was merely to state that a function throwing an exception [1] doesn't introduce memory unsafety. --- [1] Notably, we call this "panicking" in Rust-speak; does the fact that we call it something different from "exceptions" confuse people? Probably at least one.
- wizzwizz4 7y agoWe call it panicking because there's no assumption that you're always able to catch panics. Panicking is an AAAH EVERYTHING WENT WRONG kind of thing, which might trigger an immediate abort if the program is compiled in super-ultra-speedy-make-debugging-really-hard mode; if your code panics, it's always the programmer's fault. The language provides a way of kinda-sorta recovering from an everything-goes-wrong situation only to be nice to you, and not because that's a thing that's generally possible. You can't always recover from a segfault, or a buffer overrun, or the rest of the kind of things that cause panicking, even if you know that they're theoretically possible in advance, because if you could you would've fixed them already. The best you can do is make your web server return a 500, send logs, ditch its cache, restart in a sane state and hope for the best. You're not recovering that half-finished task, because the programmer can't reason about the program state in a situation where their code has been shown to be wrong. Panics are only for exceptional failure cases. If this confuses people, it's (probably) because they only thought they understood; they needed confusing.
- shadowgovt 7y agoAll of that having been said... If you're talking about Rust, I can't comment directly because I haven't used Rust, but I've totally used Go's panic / recover to implement "return" and "break loop" in a language interpreter. I should really rewrite that thing to do something more sane like bundle up a continuation state to return to, but I was feeling lazy. ;)
- mceachen 7y agoIt depends on the problem domain. If you've got very tightly controlled inputs, it's not unreasonable to expect tightly-bound results (like the last example in the article). If you're writing intermediary code between unsafe inputs and other libraries, there might be a reasonable boundary to catch all unknown errors and wrap as a failure. In PhotoStructure's case, it's an easy solution: I simply don't import the given file. There may be a similar reasonable boundary in your problem space.
- shadowgovt 7y agoAgreed. And sometimes, the right solution is to assume inherently unsafe code and do one's best to guarantee safe behavior anyway. Operating systems and web browser tab isolation, for example, operate under this principle (as do many web servers that use multithreading to support multiple requests in the same process, so that one bad request doesn't deny service to N hundred completely unrelated user sessions). ... but if one is doing that, one should do it very explicitly. I prefer a codebase that separates regular flow of operation from the "catch-all" or "panic-recover" loops that indicate "The buck stops here for catastrophic failure."
- abraxas 7y agoI don't know Rust at all but what you're talking about sounds equivalent to (much maligned) Java's checked exceptions system? I never understood the hatred checked exceptions received especially from the younger crowd. I still write Java at work and I still use checked exceptions whenever they indicate an error condition that must not be ignored by the client code. Many new to the project developers hate me for it initially because they can't just "roll out a feature" without being forced to take care of the corner cases but over time they love the discipline that's imposed on them by checked exceptions.
- hocuspocus 7y ago> I don't know Rust but it sounds like equivalent to much maligned Java's checked exceptions? Ergonomics are important. Chaining calls to functions that return a monadic Result/Either type is easier and neater.
- deleted 7y ago[deleted]
- svieira 7y agoThe problem with checked exceptions as implemented in Java is that not all exceptions are checked, but all error handling uses the same mechanism. Midori nicely separated panics (programmer or system errors) from exceptions. Panics _could not be caught_ - they crashed the process. (Processes were therefore really cheap in Midori). Java, on the other hand, put common programmer errors into the exception category in order to make it easier to work with common code (e. g. `IndexOutOfBounds` should be checked or impossible, but arrays are so common, they decided not to require it and they needed to be backwards compatible so they couldn't make array access return a `Result`-style object). That said, using checked exceptions well is a great aid to making the code base understandable!
- svieira 7y agoAnd for those who are interested in this kind of thing, check out Zig's return traces (a kind of inverted stack trace) for other good ideas on how to do exceptions in a new way: * https://ziglang.org/documentation/master/#Error-Return-Traces https://ziglang.org/documentation/master/#Error-Return-Trace... * https://ziglang.org/#A-fresh-take-on-error-handling https://ziglang.org/#A-fresh-take-on-error-handling
- shepmaster 7y ago> so that I can do things like internationalization Can you expand a bit on how you do this internationalization? I've got a low-priority issue [1] to investigate how to integrate SNAFU and Fluent to get i18n for error messages, but knowing how someone does it today would be super helpful! [1]: https://github.com/projectfluent/fluent-rs/issues/107 https://github.com/projectfluent/fluent-rs/issues/107
- lern_too_spel 7y agoExceptions are typed in most staticly typed languages as well.
- tomphoolery 7y agoI felt the same way about Go's error handling, or lack thereof, which forces you to implement your own error handling system. But as it turns out, if you are forced to do that, you will create an error handling system that is easy to follow with zero GOTOs (as is the case with exceptions). Although it makes Go code a little more cumbersome to write, the trade-off is that when you read Go, you're never unsure as to where the "code path" is, it's very clearly laid out for you.
- dgellow 7y ago> Quite often I need to know exactly which error messages will be thrown so that I can do things like internationalization. Internationalization of error message? I didn't know that was a thing! I'm curious about that, do you have some examples I could check?