7 ms·
> Error handling has been wrong since the beginning 100% this. The very concept of "error" is philosophically unsound. There are no errors; only conditions t
by enriquto 6y ago
> Error handling has been wrong since the beginning
100% this. The very concept of "error" is philosophically unsound. There are no errors; only conditions that you dislike. It is unfortunate that programming languages allow to express your emotional detachment to one of both cases of a branch. Nothing good can come from that.
I yearn for a language with no error handling nor exceptions. Just plain language constructs to deal with the state of the world around the program, without unnecessary emotional attachment to certain flow paths.
- hacker_9 6y agoThe issue is we have to pre bake decisions into the application, and until the application is literally an AI this is as good as it gets. When building a program 'errors' occur all the time, but we make design decisions to handle them because we can identify the right path forward in the given context.
- Kaze404 6y agoIsn't that what the Result type on Rust is? Sure, one of the branches is still called Error but it's just a plain language construct (a sum type you can write yourself).
- creata 6y agoYep, although I guess the Try trait[0] and the corresponding ? operator count as a special error handling language construct. [0]: https://doc.rust-lang.org/std/ops/trait.Try.html https://doc.rust-lang.org/std/ops/trait.Try.html
- ymbeld 6y agoThe Result type is specifically designed to store value-or-error. One may use it diffently but that’s what it’s made for. The library designers had a choice between making a generic this-or-that type or a value-or-error type and they chose the latter because they thought that that would be the common this-or-that use-case. Even Haskell’s more generic-sounding “Either” type is made for the same purpose: the “right” (as in correct) variant is the value while the left side is the error, by convention.
- Kaze404 6y agoI don't understand what the problem is, in that case. Is it just the fact that it's called an Error instead of something more generic? Not trying to sound dismissive, just trying to understand if there's something I'm missing.
- deleted 6y ago[deleted]
- zanellato19 6y agoWhile Result is designed for that, it was built with an Enum (see here: https://doc.rust-lang.org/src/core/result.rs.html#241-251 https://doc.rust-lang.org/src/core/result.rs.html#241-251) So you can also build an enum that doesn't have any explicit mention of which is the right path
- deleted 6y ago[deleted]
- carapace 6y agoAye. throw/raise is GOTO. Forth?
- enriquto 6y ago> throw/raise is GOTO. Worse, it's COME FROM! https://en.wikipedia.org/wiki/COMEFROM https://en.wikipedia.org/wiki/COMEFROM
- simiones 6y agoTo be fair, throw is GOTO. Catch() is COMEFROM :).
- Ace17 6y agoTechnically, `throw` is `goto somewhere`.
- marcosdumay 6y agoI guess gettout wasn't well accepted by the committees of the time.
- carapace 6y agoAh, my peeps! I love you guys. enriquto when you talk about "a language with no error handling nor exceptions" it reminds me of a crazy idea i was toying with: what if you made all "exceptions" require handlers, e.g. what if every divide had to be accompanied by code to deal with divide-by-zero? In other words, DIV(X, Y, Foo) would be (X/Y if Y != 0 else Foo()) And so on...
- heja2009 6y agothat's the way some embedded control systems are designed. with some (many) errors (can't read/write) being fatal and shutting down the system after an alarm is sent.
- simiones 6y agoWell, what you're saying is exactly the reason why java called them Exceptions and not Errors (well, Error also exists, but it is generally reserved for very nasty problems). Anyway, you can't just define the problem away, or else you end up with Go style error handling - that is exactly what a language with no built-in support for errors looks like. Languages need to offer control flow mechanisms that allow you to separate common cases in the code from the uncommon cases. Especially since for most code, the uncommon cases appear deep in the bowels of an application, and the only way to handle them is to ask an actual human to handle them, usually on the opposite side of the application stack. For a more reified implementation of this pattern, the Common Lisp Condition system is very interesting. It is similar to most Exception systems (code can raise a Condition, at which point a handler for that Condition is searched for up the call stack), but with one crucial difference: when raising a Condition, you can also specify Restarts - alternatives for how to proceed. Condition handlers can choose whether to cancel the execution flow and handle the condition with their own logic, OR they can choose to invoke one of the Restarts offered along the condition, based on their own logic. An example would be something like: Raise ConfigFileNotFound; Restarts: ContinueWithDefaults, Retry, ContinueWithOtherFile(newFileName). Then, a Condition handler (possibly a User) can choose to stop the application, or it can choose to continue with the defaults, or it can create the file with its own defaults and Retry, or it can try a different config file path. This offers a lot of flexibility and has uses outside the idea of handling errors.
- enriquto 6y ago> Languages need to offer control flow mechanisms that allow you to separate common cases in the code from the uncommon cases. Strong disagree with this sentence. It represents the exact opposite of what I deem a good programming language. The difference between "common" and "uncommon" execution paths must be of no bearing. Moreover, this "likeliness" depends on the (unknown to the programmer) usage that the program will be put through. For all you know, the uncommon path may be the only one that will be ever traversed in all instances of your program. A correctly specified program must deal with all possible input conditions, and that includes missing files, inconsistent parameters, and lack of resources. A filename existing or not is the same boolean value as an integer being even or odd.
- blacktriangle 6y agoMaybe CL got this right with the condition/restart system? In addition to their utility for experimental programming, conditions work really well for handling errors programatically. The general problem seems to be something weird happening far down in the system, for which the correct way forward is dependent on how we got there. This situation can't be handled where the issue happened since that would break encapsulation, but unrolling the stack all the way up blows away the context that is necessary to understand how to move forward. I don't see how a system that either unwinds the stacks (throwing errors) or tries to encapsulate the state through the system (Either) would truly solve the issue.
- enriquto 6y agocomputers don't do "weird" things. If you think this is the case it means that the interface you are using is incomplete or not well-specified.
- finder83 6y agoI agree, for the actual handling part, I think CL's error system is the best I've seen, and I'm surprised that more languages don't implement a similar system. It doesn't solve the issue of forcing programmers to handle errors..but then, CL doesn't care a lot about hand holding.
- masklinn 6y agoOne advantage of condition systems is that the caller gets to decide whether the condition is even an error. Though the restarts are still under the control of the callee.
- golergka 6y ago> There are no errors; only conditions that you dislike. This is true in mathematical sense, but unhelpful in UX sense.
- Ace17 6y agoQuite the opposite IMHO : when your program interacts with a user, you cannot panic the program each time something unexpected happens. Here are some examples of unexpected conditions: - "Null pointer dereference" - "Out of memory" - "Disk is full" - "File does not exist" - "File does not exist in cache" - "File exists but is corrupt" - "Access denied" - "Connection reset by peer" It's pretty obvious that all of the above is generally unwanted most of the time. However, putting them all in the same bag labeled "error", and forcing them to be treated the same way might be counterproductive. Sometimes you might want to panic. Sometimes you might want to retry. Sometimes you might want to ignore! Now, if your program isn't interactive (such as a compiler), halting on any error might be a choice. But you still have to provide contextualized and accurate error messages, which is easy for the case "File does not exist", and a lot less easy for the case "Out of range index".
- randyrand 6y agoA better word might have been “failure”. Something is a failure when it fails to do what it says it does. openfile(); If openfile() does not open a file, then it failed. This terminology makes it clear we are not just bubbling up errors. It’s the function itself which failed.
- deleted 6y ago[deleted]
- kazinator 6y agoWell, no, there are errors, and then there are environmental situations (if we ignore, for a minute, hardware malfunctions). like "file not found", "disk full". Something in between like "out of memory". Misusing an object as the wrong type, or division by zero, or accessing missing memory are errors. These usually point to defects in the program, or in some cases defects in the program's defense against bad inputs. There are related errors are the hardware level, like numeric exceptions and bus errors. Without these, machine-language programs just lock up or produce garbage results. Situations like "file not found" or "host not reachable" are usually environmental conditions, and not internal problems. There are ways in which they can be internal problems; two modules in a program might be related in such a way that one prepares a file that the other expects to exist, and there can be some bug in that. Then there are situations like "out of memory" or "disk full" are somewhere in between. All the operands to the calculation exist and are well-defined, the operation is correct, but just there is a resource issue. In pure computing theory, these situations are the heart of the distinction between simulating a Turing machine by means of a finite tape, and the Turing machine abstraction, as such, which has unlimited tape. In summary, there are basically three categories: errors (programming mistakes), environmental situations (issues in presentation of the inputs to the program, like asking it to operate on a file that doesn't exist, or connect to a host that is down) and resource exhaustions (out of some type of storage). There is no emotional attachment in this classification whatsoever; and there is value in their separation. Then there is another category of errors: faults in the hardware. The foregoing assumes that there are no malfunctions in the hardware; no cosmic rays that collide with silicon, flipping the values of bits and such. In some situations, you need a demonstrated strategy for these. Like what if an error happens in a DRAM chip that is not detected and corrected.
- xxpor 6y agoI'm confused. Isn't that just C? There's no errors in C, or exceptions. The only exceptions are interrupts/signals, but those aren't part of the language, but the machine or OS.
- enriquto 6y agothere's nothing to be confused about, C is one of the few languages that gets it right (the base language... the stdlib is a different story)