6 ms·
I always think more languages should support Result… but only to handle expected error states. For example, you may expect that some functions may time out or t
by tyleo 1y ago
I always think more languages should support Result… but only to handle expected error states. For example, you may expect that some functions may time out or that a user may attempt an action with an invalid configuration (e.g., malformed JSON).
Exceptions should be reserved for developer errors like edge cases that haven’t been considered or invalid bounds which mistakenly went unchecked.
- embedding-shape 1y agoI usually divide things in "errors" (which are really "invariant violations") and "exceptions". "exceptions", as the name implies, are exceptional, few and when they happen, they're usually my fault, "errors" on the other hand, depending on the user, happens a lot and usually surfaced to the user.
- tcfhgj 1y agowhy not divide things into errors and bugs (programming errors)?
- sanex 1y agoNot all exceptional circumstances are bugs
- embedding-shape 1y agoI'm currently working on something that requires a GPU with CUDA at runtime. If something went wrong while initializing the GPU, then that'd be an exceptuion/bug/"programming error" most likely. If the user somehow ended up sending data to the GPU that isn't compatible/couldn't be converted or whatever, then that'd be an user error, they could probably fix that themselves. But then for example if there is no GPU at all on the system, it's neither a "programming error" nor something the user could really do something about, but it is exceptional, and requires us to stop and not continue.
- deleted 1y ago[deleted]
- tyleo 1y agoThat’s interesting. I’d actually consider this a user error because it’s only in the user’s power to fix it. For example: 1. You’d want to display a message that they need a GPU. 2. Call stack information isn’t helpful in diagnosing the issue.
- 9rx 1y ago> If something went wrong while initializing the GPU, then that'd be an exceptuion/bug/"programming error" most likely. That depends if it is due to the programmer making a mistake in the code or an environmental condition (e.g. failing hardware). The former is exceptional if detected, a bug if not detected (i.e. the program errantly carries on as if nothing happened, much the dismay of the user), while the latter is a regular error. > But then for example if there is no GPU at all on the system, it's neither a "programming error" nor something the user could really do something about, but it is exceptional Not having a GPU isn't exceptional in any sense of the word. It is very much an expected condition. Normally the programmer will probe the system to detect if there is one and if there isn't, fall back to some other option (e.g. CPU processing or, at very least, gracefully exiting with feedback on how to resolve). The programmer failing to do that is exceptional, though. Exceptions are "runtime compiler errors". A theoretical compiler could detect that you forgot to check for the presence of a GPU before your program is ever run. The grey area is malfunctioning CPU/memory. That isn't programmer error, but we also don't have a good way to think about it as a regular error either. This is what "bug" was originally intended to refer to, but that usage moved on long ago and there is seemingly no replacement.
- deleted 1y ago[deleted]
- 9rx 1y agoBoth bugs and exceptions can be reasonably thought of as programmer error, but they are not the same kind of programmer error. Exceptions are flaws in the code — conditions that could have been caught at compile time with a sufficiently advanced language/compiler. Whereas bugs are conditions that are programatically sound, but violate human expectations.
- ninetyninenine 1y agoA little nuance: bugs are not just conditions that are programmatically sound. They can encompass exceptions. If a bug triggers an exception then with a strong compiler that is sufficiently advanced then these bugs can be found by the compiler.
- 9rx 1y agoBugs require execution so a compiler cannot find bugs. Exceptions also require execution, but that does not suggest that they are encompassed by bugs. The lack of a third term tells that there is no overlap. If "bug" covered both exceptions and where human expectations are violated, there would necessarily be another term just for the case where human expectations are violated. But there is no such term... ...that I've ever heard. If it is that I've been living under a rock, do tell.
- ninetyninenine 1y agoNo you haven’t been living under a rock your definitions are just off and you didn’t read carefully what I wrote. Or you’re just overly pedantic. I wrote bugs can cover exceptions. Think hard about what that sentence means in English. If I can do something it means I can both do something and not do something. So that means there are exceptions that are bugs and exceptions that are not bugs. The reason why it’s important to illustrate this difference is because a large, large number of exceptions occur as a bug.
- 9rx 1y ago> So that means there are exceptions that are bugs Which, like before, is false. Are you, perhaps, confusing exceptions (the concept; what we're talking about here) with the data structure of the same name? A bug could erroneously lead to the creation of an exception (data structure), but that wouldn't be an exception (concept), that'd just be a bug. There is no situation where an exception (concept) is also a bug, unless you take "bug" to mean something akin to general "programmer error", where exceptions are subset thereof. But, as before, we know that's not how "bug" is used as there is no other terminology for human expectation violations to fill the void. No need as that is already what "bug" refers to. > a large, large number of exceptions occur as a bug. That doesn't really make any sense. Maybe if, again, you have confused exceptions (concept) with exceptions (data structure), then it could start to mean something, but even then "large, large" is one hell of a claim. Let's be real: The vast majority of exceptions (data structure) are created by programmers who mistakenly believe that "exception" is another word for "error". While not exactly a good idea, that use falls under neither exceptions (concept) nor bugs. In second place, exceptions (data structure) are created due to exceptions (concept). I'm sure exceptions (data structure) being created due to bugs has happened before, but I've never seen it.
- kubanczyk 1y agoThat's subtly different. It's secondary whose fault is this, what primarily matters is whether you should continue with the rest of the process. There is always a cleanup layer, the trick is to choose well between 1 and 2: 1. Some code in the same OS process is able to bring data back to order. 2. OS can kill the process and thus kill any corruption that was in its address space. 3. Hardware on/off button can kill the entire RAM content and thus kill any corruption that spilled over it. Take for example an unexpected divide by zero, that's a classic invariant violation. The entire process should blow up right there because: - it knows that the data in memory is currently corrupted, - it has no code to gently handle the corruption, - and it knows the worst scenario that can happen: some "graceful stop", etc., routine might decide to save the corrupted data to disk/database/third-party. Unrecoverable panic (uncatchable exception) is a very good generic idea, because persistently-corrupted-data bug is a hundred times worse than any died-with-ugly-message bug as far as users are concerned.
- tcfhgj 1y ago> Take for example an unexpected divide by zero, that's a classic invariant violation. The entire process should blow up right there because: > - it knows that the data in memory is currently corrupted, > - it has no code to gently handle the corruption, are these conditions or implications? - corruption isn't necessary: it could be the consequence of a bug - corruption can be handled sometimes: fetch the data from the source again, apply data correction algorithms - you know and control what the graceful stop does; maybe not save the corrupted data to disk? or maybe save it to disk and ask the user to send it to you
- kubanczyk 1y agoI took several assumptions to build an argument why some errors should result in process-level termination. By "corruption" I mean much more than merely a hardware bit error. I mean any situation when data no longer has a meaning for a user. By "unexpected" I mean that the program has not been prepared to deal with the situation: there is no code there to "fetch the data from the source again", etc. > you know and control what the graceful stop does No, in fact I'm exploring here situations when I don't know this with certainty.
- deleted 1y ago[deleted]
- teraflop 1y agoI find it kind of funny that this is almost exactly how Java's much-maligned "checked exceptions" work. Everything old is new again. In Java, when you declare a function that returns type T but might also throw exceptions of type A or B, the language treats it as though the function returned a Result<T, A|B>. And it forces the caller to either handle all possible cases, or declare that you're rethrowing the exception, in which case the behavior is the same as Rust's ? operator. (Except better, because you get stack traces for free.)
- tyleo 1y agoYou know, I’ve also found this funny. I like the declaration side. I think part of where it misses the mark is the syntax on the caller side. I feel like standard conditionals are enough to handle user errors while the heavy machinery of try-catch feels appropriately reserved for unexpected errors.
- lock1 1y agoProbably, the problem with Java's `try-catch` is it's not composable and has an abundance of unchecked exceptions (could mess up `catch` type). In Rust, you could just `?` to short-circuit return or do another chained method call `result.map(...).and_then(...).unwrap_or(...)`. And more importantly, I don't think there's any JEP trying to improve checked exception handling.
- cies 1y agoOnly it is not considered by the type checker. Result brings errors into the realm of properly typed code that you can reason about. Checked exceptions are a bad idea that did not work out (makes writing functional code tedious, messes with control flow, exceptions are not in the type system).
- Borealid 1y agoThe only difference between a `fun doThing: Result<X, SomeError>` and a `fun doThing: X throws SomeError` is that with the checked exception, unpacking of the result is mandatory. You're still free to wrap the X or SomeError into a tuple after you get one or other other. There is no loss of type specificity. It is no harder to "write functional code" - anything that would go in the left() gets chained off the function call result, and anything that would go in the right() goes into the appropriate catch block.
- spacechild1 1y ago> Exceptions should be reserved for developer errors like edge cases that haven’t been considered or invalid bounds which mistakenly went unchecked. Isn't this what assertions are for? How would a user even know what exceptions they are supposed to catch? IMO exceptions are for errors that the caller can handle in a meaningful way. Random programmer errors are not that. In practice, exceptions are not very different from Result types, they are just a different style of programming. For example, C++ got std::expected because many people either can't or don't want to use exceptions; the use case, however, is pretty much the same.
- tyleo 1y agoI’ve often seen assertions throw exceptions when violated. Users don’t catch exceptions, developers do. Users interact with the software through things like failure pop ups. You’d need to check that there’s a failure to show one, hence returning a Result to represent the success/fail state.
- spacechild1 1y agoWith users I meant library users, not end users. > You’d need to check that there’s a failure to show one You can do this with either exceptions or Result types. At the end of the day, it is a matter of culture and personal preference.