[swift-evolution] [Proposal idea] Improved interop for ErrorType->NSError

Paul Cantrell cantrell at pobox.com
Tue Dec 22 11:30:50 CST 2015


> On Dec 21, 2015, at 9:12 PM, Charles Srstka via swift-evolution <swift-evolution at swift.org> wrote:
> 
> And my two cents is:
> 
> NSError is antiquated, and enums conforming to ErrorType, with associated types on the case values, are much better. They are cleaner, they are easier to use, and they are nicer to look at.

Digressing a bit, I’ve moved away from enums and toward structs for custom ErrorTypes, for several reasons:

1. Associated values are tuples. This is a big problem in a public API. Any tuple change is a breaking change, and errors thus cannot gain any new diagnostic information with breaking the API:

    enum MyError: ErrorType
        {
        case FileNotFound(url: String) // 1.0
        }

    ↓

    enum MyError: ErrorType
        {
        case FileNotFound(url: String, errno: Int?) // Oops! New major release
        }

Structs allow for future expansion:

    struct FileNotFound: ErrorType
        {
        let url: String  // 1.0
        }

    ↓

    struct FileNotFound: ErrorType
        {
        let url: String
        let errno: Int?  // No problem! 1.1
        }

2. Structs allow error-specific helper methods and derived properties, which can be useful.

3. Structs can implement protocols, which allow shared handling of error cases with shared structure.

> Comparing them is nicer:
> 
> if case let .FileNotFound(url) = error {
>     // handle the error
> }

4. But comparing structs is nicer still, especially when dealing with an optional error. With an enum:

    func handleFileNotFound(error: ErrorType?)
        {
        if let error = error
            {
            if case MyError.FileNotFound(let url) = error
                { print(url) }
            }
        }

But if it’s a struct:

    func handleFileNotFound(error: ErrorType?)
        {
        if let error = error as? MyError.FileNotFound
            { print(error.url) }
        }

Or if you don’t need the wrapped value:

    func handleFileNotFound(error: ErrorType?)
        {
        if error is MyError.FileNotFound
            { retry() }
        }

So much more readable than the “if let, if case let” dance!

Hmm, I wonder if #1 or #4 suggest any language changes to propose for this list.

The one big advantage of the error enum is one can use it to enforce handling of all error types in a switch — a need which I have yet to encounter in practice.

Cheers,

Paul


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151222/e13e8a48/attachment.html>


More information about the swift-evolution mailing list