7 ms·
> Now how is that any different from raising an exception? Exception bubbling is implicit. There's no way to know which exceptions can be thrown from a functi
by kaoD 8y ago
> Now how is that any different from raising an exception?
Exception bubbling is implicit.
There's no way to know which exceptions can be thrown from a function just by looking at its code, nor looking at the called-functions code. You have to keep in your head all the call chain up to the first function that does not call any other function (good luck with that).
Even worse: we don't even know _where_ the function can stop running and start unwinding. This leads to defensive programming. Hello try-catch soup!
It's a slippery slope that gets worse and worse with each abstraction layer.
Languages with typed errors have been nothing but a joy for me.
- rcfox 8y ago> There's no way to know which exceptions can be thrown from a function just by looking at its code, nor looking at the called-functions code. But is this different from error codes? Does seeing a file open tell you every error that might occur from that? If you're arguing that you could just look at the file-open code to see the errors it returns, couldn't the same apply for seeing which exceptions are thrown?
- kaoD 8y ago> If you're arguing that you could just look at the file-open code to see the errors it returns, couldn't the same apply for seeing which exceptions are thrown? No, because then you have to look at every function inside there. And there every function inside those functions. And then... With typed error handling they're only one-level of abstraction deep. Actually zero-levels, since your function won't typecheck unless you handle the errors.
- wvenable 8y agoSo if you have a potential call chain of dozens of methods, your error return includes every single possibility? That's pretty doubtful. What happens is the same thing that happens with checked exceptions; the errors are massaged or placed untyped in properties and while you're handling all the errors you're doing it in a sloppier way.
- kaoD 8y ago> So if you have a potential call chain of dozens of methods, your error return includes every single possibility? Mostly yes, usually as a sum type. Pattern matching is your friend. > the errors are massaged Why would I take the extra effort? Unless it's my responsibility to handle it (i.e. it's part of the function's logic) I will just return it untouched and let the consumer decide what to do (if anything at all). > or placed untyped That's not possible (at least in the typed languages I tried).
- wvenable 8y agoJava has checked exceptions (which honestly is more like error-return) and the innerException property is used extensively to hold the "real" exception and, of course, it's type is just "Exception". Making the real error types part of the signature of the method means that implementation changes require changing the signature, completely breaking encapsulation. In fact, I'd argue it makes polymorphism completely impossible.
- kaoD 8y ago> Java has checked exceptions (which honestly is more like error-return) and the innerException property is used extensively to hold the "real" exception and, of course, it's type is just "Exception". Yeah, well, Java's semantics and programer laziness make a mess. News at 11. > I'd argue it makes polymorphism completely impossible. Oh, so two birds with one stone!
- wvenable 8y agoIt's like it's 1992 all over again. Every change requires changing every caller everywhere. Yes, it's an improvement now that the typechecker will tell us all the places we need to change but it still doesn't sound enjoyable or useful.
- kaoD 8y ago> Every change requires changing every caller everywhere I don't see why.
- wvenable 8y ago> There's no way to know which exceptions can be thrown from a function just by looking at its code, nor looking at the called-functions code. It's good you don't actually need to know that! And if you did, it wouldn't matter anyway because somebody could come along in the future and change that code that currently uses a database and change it a web service and all that knowledge would be wasted. All you need to know is what exceptions you can handle and where you handle them. What error codes or exceptions each individual function everywhere up the call chain can raise is almost inconsequential.
- kaoD 8y ago> All you need to know is what exceptions you can handle Ah, so that's "all" I need to know! And that's what typed errors do.
- wvenable 8y agoYou might only be able to handle restartable network exceptions. In my case, that might be a single base type. So I put a try block in where I can handle that exception (where my network code starts) and I'm done. Do I need to check the return type of the thousands of methods that might make up that operation? Nope. Typed errors make me do a lot of work passing stuff around and declaring types that literally don't matter. If somebody adds a new method that does another network call, I'm still good and I didn't have to do anything.
- kaoD 8y agoYou like implicit. I don't. I don't think we can discuss deeper than that.
- wvenable 8y agoActually, for the most part I don't like implicit. But I also like encapsulation and polymorphism and you can't have those things if you are exposing implementation details all over the place. The other thing I don't like is pointless boilerplate code. But I do like strongly-typed languages and originally I thought I'd like checked exceptions before realizing just how wrong that concept is. It's not hard to see the parallels between checked exceptions and error returns.
- shawnz 8y agoIf you want strongly typed errors then you could use a language with checked exceptions (Java). What you are describing is not a complaint about exceptions, it's a complaint about weakly typed errors. You can have the same problem even if you don't use exceptions -- e.g. what happens if one of your inner-inner-inner functions returns null when the docs say it shouldn't? You will just end up with if-null soup instead of try-catch soup if the language doesn't support exceptions.
- kaoD 8y ago> what happens if one of your inner-inner-inner functions returns null when the docs say it shouldn't? My choice of language wouldn't have the concept of "null". If it somehow returns an Option type... well, the docs would say it, and it won't typecheck unless I handle it. > If you want strongly typed errors then you could use a language with checked exceptions (Java). Yes, typed error handling looks an awful lot like Java's checked exceptions. Buuuuut exceptions magically unwind the stack at unknown points. I don't like my stacks unwinded unless I explicitly tell them to. Function exit points should be explicit. Also: it has unchecked exceptions too, runtime exceptions (null pointers, anyone?) and lacks the expressiveness to handle error propagation while not being a pain in the ass.
- shawnz 8y agoI actually think checked exceptions make handling error propagation much easier than Option types. In a language with checked exceptions, if you want to propagate the error, all you have to do is declare that intent. With Option types, there is a need for boilerplate unwrapping code in almost every place where you want to use the value.
- kaoD 8y ago> With Option types, there is a need for boilerplate unwrapping code in almost every place where you want to use the value. Disagree, in my favorite language you just add "?" to the possibly-erroring function et voilá, error propagated. Even better, since errors are functor-like (map) and monad-like (and_then), I'm mostly never unwrapping myself. This has the advantage that it's explicit, instead of exceptions implicitly returning early (sometimes to great amusement).