3 ms·
Swift's error handling model essentially tosses type information out the window. I really don't understand why it was created instead of a first-party Result ty
by chris_7 10y ago
Swift's error handling model essentially tosses type information out the window. I really don't understand why it was created instead of a first-party Result type.
- kibwen 10y agoFirst-class error handling is a little more ergonomic than just having a `Result` type that is used by convention, so I can see why Swift went that route if they were looking to improve ergonomics a bit. Rust has been gradually working on making its own `Result` type a bit more first-class, first with the `try!` macro, and in the future with the `?` operator which will improve upon `try!`.
- chris_7 10y agoIf the type signature was: func throwing() throws FooError -> Int or even: func throwing() throws (FooError, BarError) -> Int to create an implicit sum type, I'd find it acceptable, but not being able to tell what types of errors an API will throw is far from ergonomic - you'll need a catch-all block if you use anything but NSError[1] or ErrorType, even if you know the function only throws FooErrors. [1] this is especially weird because NSError is just some random Foundation class, it's not anything inherent to the Swift language.
- lomnakkus 10y agoOne reason to avoid explicit lists of "error types" (exceptions) for methods is that method parameters are usually covariant whereas you really want exceptions to be contravariant[1]. This has big implications for higher-order functions and it's why everybody rightly hates explicit "throws" clauses in Java. [1] Or to put it in more practical terms: Imagine two classes/interfaces A and B where B subclasses A. Any method on B that overrides a method on A is free to accept a "more restricted" parameter than the method on A, but since it (presumably) does something more specialized it must also be able to throw more exceptions that A's method was. (Maybe it's accessing files and needs to be able to throw FileIOError, or whatever.)
- chris_7 10y agoIdiomatic Swift shouldn't really be using inheritance though, protocols (which support associatedtype, making varying errors types not an issue) are generally preferred. Functions would be free to just "throws ErrorType" (probably the default for blank "throws", to avoid breaking backwards compatibility) if they really wanted to though, just like they can accept and return "Any", and the behavior would be identical to today. I prefer Result though, which just solves the problem of disjoint error types by using "mapError" and a sum type.
- riwsky 10y agoYou have the variance bit totally backwards. Methods are contravariant on their input and covariant on their results. A method which can only feed cats is not a method which can feed all animals. A method which gives me a cat, well, that is certainly a method that gives me an animal. Exceptions are another type of result. Please see https://en.m.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science) https://en.m.wikipedia.org/wiki/Covariance_and_contravarianc... for more info. I agree with your assertion that this is part of what makes explicit throws a pain, though. I hadn't thought about it that way, thanks for the insight.
- austinz 10y agoI've seen interest on the lists for modifying the model to allow a single failure type to be specified. I hope someone will write up a proposal once August rolls around and the lists are open again to new feature ideas.
- joewillsher 10y agoHere’s your explanation: https://github.com/apple/swift/blob/master/docs/ErrorHandlingRationale.rst https://github.com/apple/swift/blob/master/docs/ErrorHandlin... There has been discussion about statically typed errors on the evolution mailing list — some core team members said they may look into in the future and others seeming more doubtful of its usefulness. Why do you think a typed error handling model is better than introspecting the error at the catch site, I’m not sure I buy it?
- chris_7 10y agoErrors should be Just Another Value, so the difference between untyped errors and typed errors is the same as the difference between just using Any for every parameter and return value, and using actual types. You can use Any for everything, and it can even be totally safe if you use as? correctly, but it's obvious why no one does that. It's not obvious to me why people are fine with that situation for errors - again, the catch-all handler issue mentioned above, and the bizarre special-casing of NSError.