4 ms·
People say they hate exceptions much, but what they actually hate is either one of two subsets of exceptions: Java-esque checked exceptions and C++-style untype
by lifthrasiir 6y ago
People say they hate exceptions much, but what they actually hate is either one of two subsets of exceptions: Java-esque checked exceptions and C++-style untyped (and heavy) exceptions. Result type is an implementation of much wanted middle ground: explicitly typed but ergonomic enough exceptions. Its non-abrupt nature is, in my opinion, just a side effect.
By comparison exceptions, as a means to abruptly terminate the thread of computation, is not something you can simply replace (unless you do total programming). Most languages with result types do have exceptions in this sense: ML `raise`, Haskell `error`, Rust `panic!` etc. Passerine seems not much different. (Note: the whole error system is, as far as I see, completely unimplemented.)
- lopatin 6y agoLanguages that do Result + panic, or languages that do checked + unchecked exceptions. Which is best? IMO, I think "Result + panic" works better because it's a cleaner separation in the sense that handling panics is strongly discouraged. Whereas handling unchecked exceptions happens all the time, and leads to confusion. Edit: To clarify, I would consider Go to be "Result + panic" even though it doesn't have a Result interface. It has a convention of returning a tuple of "value, err", which is handled by the caller and is essentially an informal Result.
- lifthrasiir 6y ago"Panic" is a fancy name for unchecked exception. It can arise from any code, for example, by out-of-index accesses or arithmetic overflows. In the other words, if you want to allow, say, `arr[0]` without any checking, you should accept that it can abruptly terminate the current thread. (Pony is a rare example of the contrapositive.) I too agree that "Result + panic" is better for the very same reason, but it doesn't mean exceptions are gone.
- HelloNurse 6y agoHandling unchecked exceptions "happens all the time" because in certain languages and libraries, like Java, it looks like less work than tediously checking error conditions or letting the program die properly. Different kinds of software in a different language can fare very differently.
- slightknack 6y agoHey, author of this language here. I love Rust, but what I like the least about `panic!` is the lack of context it provides. I mean, sure, there's `RUST_TRACEBACK=1`, but that's not nearly as neat as a real traceback, with the appropriate context and data to help determine the root of the problem. I'm still thinking through my design options, because I've been recently reading a lot about Algebraic Effects. I'd hate to have two non-orthogonal features in a minimal language, which is why I'm waiting until more of the language has solidified and I've reached a conclusion about Algeffs before implementing the whole error system. Thanks!
- lifthrasiir 6y agoYeah, exceptions are not enough for fully reconstructing the problem! I'm not sure this can and should be necessarily fixed by changing exceptions, though. It is often the case that you need a deep trace to understand the problem and mainstream tooling is not prepared for that (I wish rr to be more widespread). For algebraic effects: I too had keen eyes to Koka and think that it might be the future. What I don't know is how to make effect types mostly invisible to users without sacrificing its power. I had been experimenting with dynamic scoping in my mind, but that feels unsatisfactory.
- cwp 6y agoResumable exceptions - ie, exceptions that don't unwind the stack when they are thrown - do let you examine the problem in situ.
- dataflow 6y agoI left this comment just a couple of days ago - I don't see any reasonable solution for this except (ha) exceptions: https://news.ycombinator.com/item?id=26198607 https://news.ycombinator.com/item?id=26198607
- ledauphin 6y agoi remembering seeing and appreciating this one a few days ago :)
- dataflow 6y agoOh cool! Happy to hear :)
- lifthrasiir 6y agoTechnically speaking cancellable sort requires non-local jumps, which includes exceptions but also many others (call/cc, delimited continuations, algebraic effects, ...). It can be also argued that the general idea of cancellation is an exception (as in futures). In any case we are not dealing with something unnecessarily requiring exceptions.
- dataflow 6y ago> which includes exceptions but also many others (call/cc, delimited continuations, algebraic effects, ...) I think you might be missing my point? How would you use call/cc or the rest with arbitrary callers? Do you write everything in that manner all the time? Do you realistically expect others to?
- lifthrasiir 6y ago> How would you use call/cc or the rest with arbitrary callers? For example, with shift/reset operators (a form of delimited continuations) you can do something like this pseudo-JS code: const cancelled = reset { arr.sort((a, b) => { if (aborted()) { shift (k) { // k is a continuation from shift to reset, // but we want early return so we discard k // and replace the reset expr with false. return false; } } return compareTo(a, b); }); // this will replace the reset expr if shift is not triggered. return true; }; Every example I've mentioned can be used to implement exceptions after all, so if you know something can be done with exceptions, you can do the same with call/cc and so on as well.