6 ms·
> What about them do you find confusing? They are non-local jumps. They make reasoning about the code very difficult. When you read code, you have to treat a
by enriquto 4y ago
> What about them do you find confusing?
They are non-local jumps. They make reasoning about the code very difficult. When you read code, you have to treat all conditions symmetrically and equally likely (e.g., whether a file exists or it doesn't). Using exceptions for control flow, as is done sometimes in python, forces an unnatural asymmetry between cases that I find confusing. And this is just when there is a single exception at stake. Typically, several exceptions fly invisibly over the same code and it becomes impossible to understand (unless you assume that no exceptions occur, which is the wrong stance to take when analyzing an exception-riddled code).
TL;DR: raise and except are a corporate-friendly renaming of goto [0] and comefrom [1].
[0] https://en.wikipedia.org/wiki/Goto https://en.wikipedia.org/wiki/Goto
[1] https://en.wikipedia.org/wiki/COMEFROM https://en.wikipedia.org/wiki/COMEFROM
- magicalhippo 4y ago> When you read code, you have to treat all conditions symmetrically and equally likely Pretty sure I don't do that when I read code. When I see "list.add()" I don't consider running out of memory and the operation failing equally likely to the list being added to. And if it did, in 99.99% of the cases I'm fine with it just bailing, because there's not much else to do at that point. I agree that using exceptions for what could be considered normal conditions is not great. Trying to open a file that doesn't exist isn't by itself an exceptional incident. The calling code might consider it an exception and decide to raise, but the IO library shouldn't.
- hnaccount_rng 4y ago> Trying to open a file that doesn't exist isn't by itself an exceptional incident. The calling code might consider it an exception and decide to raise, but the IO library shouldn't. This is a way of thinking that I don't get. Yes it's fine that an IOLibrary has to be able to handle a FileDoesNotExistError condition. But from the caller POV: I clearly instructed you to open a file of some description. I expect you to return to me a handle for said file. Everything that does not match that expectation is exceptional (to the caller). And it is that violation of expectations that is communicated by (Python's) exceptions.
- magicalhippo 4y ago> Everything that does not match that expectation is exceptional (to the caller). No. If you want to read some data from a file if it exists, and continue merrily along if it doesn't, then you cannot simply check if the file exists and then try to open it. That would lead to a race condition. The file could for example be deleted in between the two calls. The only proper way to handle that is to try to open the file, and if the result of that is FileDoesNotExistError then you continue along merrily. If the file the caller tries to open is a settings override file, say, then it's not exceptional that the file does not exist.
- acoard 4y ago> Everything that does not match that expectation is exceptional (to the caller). Sure, but saying "open this file" and having the response "nothing here, boss" is not exceptional. It's pretty normal. Isn't that just one of the two obvious options when you try and open a file? To me, exceptional would be something like "this file was open and now it's deleted."
- code_runner 4y agoIf people overuse try/catch, the code is close to impossible to read… but try/catch isn’t meant to be applied liberally throughout the code. Don’t let someone’s misunderstandings and bad code ruin it for you. Typically you just care to have one or two primary places where you actually care if something has gone wrong.
- afiori 4y agoI am convinced that a mixed goto-comefrom model would work best; consider this pseudo-syntax: try { some_code(); } catch (e) { var fixed = handle(e); if(fixed){ continue; // goes back to where the error was trown } else { beak;// gives up and continues from here } }
- enriquto 4y agoIn fact, if we want to go all-in with this style, we could remove the if/else construction altogether (from the language!) and do everything using exceptions. Since they are good for control flow, why stop here? The old-fashioned if (condition): statement_1 else: statement_2 now becomes try: assert(condition) statement_1 except AssertionFailed: statement_2 This is much clearer, since the "normal" flow of execution is emphasized, and it avoids using an ad-hoc legacy if/else construct. Moreover, it has the advantage that statement_2 can be hidden into another part of your program, wherever you want to catch this exception.
- afiori 4y agoI was thinking more of making a parallel with effect handler system currently in development for Ocaml and other research languages, you do something similar to throwing a continuations[0][1][2]. It is proposed as an alternative to both the current monad-oriented approach used in Haskell and the procedural side-effects of OCaml. To my understanding the base idea is that you can register "handlers" for (user defined) "effects" that can be emitted from normal code. Once an effect is emitted the handler receives a continuation and can decide what to do with it (call it immediately, register it in a async/await pool, repeat it 5 times). It would offer a type safe way to implement async/await as library code, which sounds quite cool. The proposed try/catch/continue was a silly bastardization of this idea. [0] https://en.wikipedia.org/wiki/Continuation https://en.wikipedia.org/wiki/Continuation [1] https://www.youtube.com/watch?v=6lv_E-CjGzg https://www.youtube.com/watch?v=6lv_E-CjGzg [2] https://www.youtube.com/watch?v=X30xmcOow2U https://www.youtube.com/watch?v=X30xmcOow2U