July 15th 2014 Thoughts on Swift

I was invited to give an informal talk about Swift at ThoughtWorks by my friend Kyle yesterday. As a functional programming aficionado, I wanted to give a high-level, executive summary of some of the functional programming features found in Swift. Historically, OS X and iOS development has been done in a very object-oriented style, but I think Swift offers some exciting avenues for taking a more functional approach to OS X and iOS development. My talk was titled “Functional Programming in Swift”, and I was lucky enough to have a receptive audience to my attempts at persuasive speaking. I’m also writing a book on Swift for Wiley, so it was great to take some of my material for a test run.

One audience member asked a provocative question: As an avid student of programming language theory, are there any Swift features that I wish Apple hadn’t included in the language? At the time, I said no: While I don’t like all the features of Swift, I respect that Apple is in a tough position with the language; they have to maintain seamless interoperability with Objective-C, C, and to some extent C++, so they’re not completely at liberty to do anything they want with Swift. I contrast this position with my dislike of Go: Despite the fact that Google was starting with a clean slate, with comparatively little compatibility baggage, they still elected to include a number of features, and exclude a number of others, that I feel aren’t appropriate to a twenty-first century language.1

However, after chatting with the gentleman who asked the question, and thinking about it for a day, I realize there are a couple things I’m not so enamored with in Swift:

  1. The distinction between classes and structs: I tend to be a big fan of languages that adhere elegantly to their paradigms. One reason I love Objective-C is that it embodies the essence of what I think object-oriented programming is all about—and nothing more. I tend to gravitate to C because, despite its drawbacks, it’s the epitome of a systems programming language; similarly, I also like Erlang because it’s well-grounded in an excellent model for concurrent programming. In contrast, I never liked C++ because it felt like a smattering of features pulled from both systems and object-oriented programming, with its own flavor thrown in. Eminently practical, perhaps, but not built on a solid theoretical grounding.

    One thing I always hated about C++ is the subtle distinction between structs and classes. Objective-C, of course, has both structs and classes, but its structs are just C structs, and it was clear when to use structs and when to use classes. C++ structs are more like classes, but not quite. I was disappointed to see Swift take the C++ route and include both, but with subtle differences. In Swift, the distinction seems to be a nod to performance,2 and in my opinion it adds additional cognitive overhead to the programmer, by forcing her to look into her crystal ball and try to anticipate how the object may be used in terms of performance and inheritance. It’s a nuance that I find to be unnecessary.

    Of course, I’m not a huge fan of object-oriented programming in general, and I would've loved for Swift to have something more akin to Haskell’s type classes, rather than OO classes and structs. But given the need for compatibility with Objective-C, I recognize that’s a pipe dream.

  2. Special language support for optional types: nil has been eradicated from Swift; in its place are optional types. Optional variables must be marked as such, and the compiler forces the programmer to deal with cases in which a value may not be present. As a fan of Haskell’s Maybe type, and an opponent of NULL, I fully embrace this decision.

    My problem with optional types in Swift, though, is that it appears that they’re essentially an enum, but with special language syntax and support. I tend to like as little magic as possible in my programming languages. For example, I’ve always liked the fact that Smalltalk’s if/else are just methods, just as Clojure’s (and, I believe, most, if not all, Lisp derivatives’) are just functions; likewise, Scala’s Option type is a class with handy methods like flatMap. Implementing basic control structures at the library level adds a degree of flexibility to the language, and I’m disappointed that Swift didn’t take this approach. While Swift’s optional types are a giant leap ahead of nil, they’re not as flexible as similar constructs in other languages.3

Of course, the fact that I can only come up with only two big things I don’t like about Swift speak well to its promise as a language, and especially its improvement over Objective-C. Despite the fact that I’m a vocal and avowed supporter of Objective-C, I must admit that I’m looking forward to seeing Swift usurp Objective-C’s prominence in Mac and iOS development.

I’ll no doubt have some more opinions about Swift, both good and bad, as I work with it more (and write more of my book). Until then, this article by a mysteriously unnamed blogger delves more deeply into some of the topics I discussed.

An earlier version of article incorrectly stated that Lisp’s if/else control structure was simply a function. On the contrary, Lisp’s if/else structures are a special form. This is a consequence of the fact that many if/else statements depend on the else branch not being evaluated if the conditional is true, and vice-versa. (One may think that this problem could be alleviated by using quoted forms, but that conclusion is incorrect. Kent Pitman has an excellent analysis on why that’s the case.) Much thanks to Alex Stoddard for kindly pointing out this error to me.

  1. I realize that bears a more thorough explanation, but since it’s not really the crux of this article, I’ll save it for another time. 
  2. Swift’s structs are value types, whereas classes are reference types. However, unlike C++, you cannot inherit from a struct in Swift, so at least it has one other big difference. 
  3. On the bright side, I anticipate that functions utilizing Swift’s pattern matching feature can be written to at least mimic some of the uses of optional types seen in languages like Haskell and Scala.