Controversial Swift Exceptions

There were some big changes to Swift this week. The most surprisingly controversial one was the adding of “exceptions.” I put those in quotes because they are quite unlike traditional exceptions in C++, C#, Java or Python even though I’ve called them Pythonesque at times.1 Whoa. People on both sides of the debate flip out on that!

There have been two types of reactions.

First (the majority) is excitement. Finally we have something to avoid all those nested and hard to read if statements.

Second (a loud minority) are those groups that hate exceptions or think Swift did them wrong. From what I can tell one group are primarily those coming from ObjcC where exceptions were always warned against. (ObjC has long had C++ styled exceptions but few use them) There’s also the Haskell/Clojure folks who also hate exceptions. Both these groups shout the, “Swift isn’t learning from the mistakes of the past and is dominated by C++ folks.” The related group (sometimes also disliking exceptions in general but sometimes a fan of C++ or related exceptions) are those who note that Swift’s exceptions aren’t even really exceptions. 

When I raise the “real exceptions” some other people flip out. So just to be clear here are the ways Swift exceptions aren’t like “real” exceptions in C++.

1. They don’t bubble up. In traditional languages if you don’t deal with an exception the function that calls you can. In Swift if you deal with a throw you have to deal with it and all possibilities. This means you have to put catch clauses for every error returning function making them more complicated to write. This whole concern is often cast as the difference between unwinding the call stack versus what is really just syntactical sugar replacing a bunch of if statements. Thus the bubble up complaint is often tied to the complexity complaint even if in practice I don’t think most people will be handling that many cases. (Edit: just to be clear – you have to either handle the error or declare it to be thrown. It’s automatic bubbling up that doesn’t happen)

2. Most problems don’t throw exceptions. Unlike most languages going past array boundaries doesn’t throw an exception. Neither does division by zero. It’s possible those sorts of things may get added to the language down the line. You can add this functionality to the base collections if you want. But unlike say Python it doesn’t come out of the box.

The problem is actually a little deeper than this. Swift could always throw ObjC exceptions via NSException. However it never could respond to traditional exceptions like a problem with a file class. Unless the Swift developers have added more magic than I’m aware of, you still can’t respond to these types of problems. So unexpectedly invalidated file handles or terminated socket connections aren’t caught. Of course most ObjC programmers didn’t catch exceptions from file handling anyways. So it’s not like this is a huge shift. However if Swift is supposed to be a language capable of systems programming (this line of reasoning goes) it really has to be able to respond to these sorts of exceptions. Further Swift should be unifying error handling not making things more complicated.

A key common feature of these complaints are that Swift’s exceptions really aren’t for handling crashes (as with C++ or even ObjC exceptions) but are for handling errors

3. Swift Exceptions can’t handle asynchronous code. C# exceptions apparently can go between threads if you do the right things.2 To be fair, especially compared to languages like Go, Swift just doesn’t do threading well at all. At best you can use existing Cocoa features to handle the cases you’d normally have threads. Things like Grand Dispatch Station. But it’s really not as good as notifications as a general part of error handling or “exceptions.” 

4. You have to label functions that use throw. I’m not quite sure why this is beyond clarifying for the caller that they have to handle exceptions and perhaps to allow easier compiler optimizations. Syntactically this is a big difference from the types of exceptions most are used to. As I said this is related to the bubbling up problem.

5. The terminology is bad for an error throwing mechanism versus exceptions. I’ve heard this one a lot from all sides. Even some on the pro-Swift “exception” side get pedantic and say it’s properly “Swift error handling.” The controversy here is that by calling them exceptions people get the wrong idea about what they can do. And, going the other way, programmers should be able to handle them being called something else despite looking like exceptions.

6. It doesn’t fix Cocoa’s error handling model. This one is where the ObjC traditionalists and those coming from other languages fight. Often (but not always) both sides hate exceptions. However Cocoa developers typically love (or are at least used to) NSError. Others say that Swift should have learned from what other recent languages have done for error handling. The problem, of course, is that most of those using Swift are using it to code Cocoa. So having to deal with the existing error handling of Cocoa probably was a smart design decision. This doesn’t end the criticism though since it then becomes, “Swift is too beholden to compatibility with Cocoa and it undermines the language.” Tied to all this are criticisms that the ErrorType protocol isn’t defined enough to do the things it ought.

 

As I said, I’ve been surprised how many discussions have been going on like this. I’ll not link to all of them. One interesting Twitter thread from a more Haskell perspective was this one by Justin Spahr-Summers. It’s long, but worth reading for some of the discussion. See also this ADN discussion which inspired some of the above. (There were also ARS discussions and several others I was following.)

 

My own view is that people are perhaps taking things too seriously. Swift is a very pragmatic language and it’s developing with a set of practical concerns. Mainly the connection to ObjC based Cocoa libraries. Maybe that’s undermining what the language could be. But especially for the next years, the primary purpose of Swift will be to code against Cocoa. For all the problems and limits of Swift exceptions, they do seem a big step up from difficult to read nested if statements. Maybe this decision will limit Swift in the future. But in the present it’ll make most people’s life easier.

Someone once said, “the perfect is the enemy of the good.” That probably applies to Swift with regards to the practical problems people are using it on.

  1. I think I called them Pythonesque because it’s fairly common in Python to use exceptions for error handling and not just unexpected catastrophic failures. To be fair not everyone agrees with that type of programming. Also unlike C++ Python’s exceptions are kind of intrinsically tied to an error state and the error state isn’t necessary catastrophic. The calling function is just supposed to respond to the error, fix things up a bit so you can continue and clear the error indicator. (See Python exceptions)
  2. I don’t code C# but this is what I’ve been told. Although apparently you have to use Task<T> instead of a normal thread creation.

Related Posts

  • 77
    Nick Lockwood has one of the best discussions of Swift exceptions I’ve found both in terms of design, problems and benefits.
    Tags: swift, exceptions
  • 63
    “Silver” brings Apple’s Swift language to the .NET and Java worlds. It brings the language not the Cocoa libraries though. Sounds like they added exceptions to let Swift work with .NET or Java better. (Personally I think Apple should add exceptions too, but I know people at Apple really don’t like…
    Tags: exceptions, swift
  • 54
    Could have sworn I’d linked to this before. But I guess not. It’s well worth reading. Reactive Cocoa in Swift. The biggest issue right now is that Swift can’t see macros in ObjC/C. Given some of the problems that introduces I’ll hold off until things get more mature. The linked…
    Tags: swift, programming

5 thoughts on “Controversial Swift Exceptions”

  1. They’re *not* exceptions, they’re just heavy syntactic sugar over the traditional approach of having methods return either a result value or an error value.

    Personally I’d have preferred returning result|error sum types as that keeps everything 100% explicit, avoids the need for even more syntactic and semantic complexity, and (coupled with a rich hierarchy of error subclasses similar to Python’s) would make best use of the type system for checking program logic at compile-time.

    However, I can understand why they went with sleight of hand to make the language look more like what most mainstream programmers are already used to. It’s just I’ve enough experience to know that the roads to hell are regularly paved with what programmers thought “helpful” or “clever”. Personally I’ll take honesty and parsimony any day as being best in the long run, even if it does make newcomers howl and whine as they’re forced to give up some of their fondly-held pre- and/or mis-conceptions first. But, eh. Programmers.

    BTW, OT, and FYI: I began my first substantive venture into Swift (2.0) this last weekend:

    http://lists.apple.com/archives/cocoa-dev/2015/Jun/msg00268.html

    Feel free to chip in over there.

  2. I get that people either simply want to ship to returning tuples or Return types. However that really doesn’t resolve the problem of too many nested ifs that make code hard to read. That appears to have been the main focus.

    The lack of error subclasses and error throwing by basic libraries really is a big issue. However I’d be shocked if those weren’t added quickly. Since I’m fairly confident they’ll be added I’d probably hold off using the throw/catch features until they are.

    I think that this is more than just making languages look like others. It’s really about trying to make code cleaner. Something can be explicit but hard to read. I credit Swift with making readability and easy to understand APIs a high priority.

    I want to jump into Swift 2.0 in more detail than I did last week. But I really need to finish an existing project first. Plus one frustrating thing for me is how much the Swift language changes. While you can convert your older code, often the changes lead to design paradigm changes as well. Last time I jumped into Swift I made a goal of waiting until it stabilizes a bit more before doing anything beyond playing in a Playground.

  3. I suspect the nested ifs problem could’ve been addressed with, say, some pseudo-goto syntactic sugar and really good pattern matching. Still, at least there’s an explict `throws` as part of the function signature; maybe if/when there’s a better error class hierarchy it’ll be possible to specify exactly which class(es) are raised and have a do-catch-catch-catch* block that pattern-matches on that. (Which, of course, tends to take us back to the nesting problem, but that’s just another reason why I prefer extracting a general solution that works across all cases rather than inventing new special forms as each new use-case crops up.)

    Re. Swift-AE bridging, it’ll be an appscript-like bridge with syntax similar to py-appscript, but using pre-generated static glues much as objc-appscript does. Although it won’t be called ‘appscript’ as that project remains dead.

    Furthermore, while I’m doing the implementation (since there’s nobody else on the planet capable of doing it right), it have to be included in 10.12 if it’s to be of any real appeal to the vast majority of Mac users. (Not an unrealistic plan; Apple considered appscript for 10.5, and it might’ve gotten in too had I not fallen asleep on the job.) And making that happen will require finding various key Apple folk to back it and getting lots of Swift users to push for it as well, along with establishing and running a vibrant user community so there actually are users for it.

    So don’t cheer too soon as I’ve neither time nor energy to be doing all that myself, which means it’ll be up to you and all the other old appscript veterans to conscript yourselves and work your own asses off to make that stuff happen.

Leave a Reply

Your email address will not be published. Required fields are marked *