By Evan Miller
June 4, 2014
Occasionally I have a good reason to pull an idea out of the queue and start writing a new computer program. Today marks one of those happy occasions. Apple announced a nifty new programming language called Swift, and as a long-time Objective-C developer, I figure I should give the language a shot. Of course, I'm old enough to know that production code is not exactly the safest space for learning a new programming language, and so I have just the excuse I need to start a new toy project, which I am tentatively calling Hecate: The Hex Editor From Hell.
(Pronounced HECK-it, thanks for asking.)
Anyway, I've been reading the Swift manual and I must say, Swift looks terrific. It doesn't have the same concurrency primitives as Erlang, nor the same numerical bent as Julia, but it has the considerable virtue of being a nearly perfect tool for the job, namely, creating and maintaing object-oriented programs. Yes, those old things.
At its core, the language is designed to eliminate bugs, but not in the academic way that, say, Haskell eliminates bugs by preventing normal people from writing code in it. Rather, it feels like it's designed to eliminate my bugs, today, without asking me to renounce my object-oriented ways and take up the white cloth of pure functions and start chanting the complete canon of category theory.
Here are a few concrete examples of recent bugs in Wizard — real, production code with tens of thousands of lines of Objective-C code, and tens of tens of users — that would have been entirely avoided if I had written equivalent code in Swift.
Bug: Renaming a function and forgetting to rename all of the overrides. Your Automobile class has a
brake() function, and you decide to rename it to
applyBrakePedal(). You get some compiler errors and fix up all of the callers, but you forget that the Batmobile subclass overrides
brake() with logic to deploy the drag parachute, and now when Batman slams on the brakes, the parachute fails to deploy and he smashes into Macy's in spectacular fashion.
The Swift Fix: Override functions must use the
override keyword. Now when you rename the superclass's function, all the subclass functions fail to compile because they're not overriding anything. Why did no one think of this before? I know you Eclipse users out there just click Refactor and go back to sleep, but for folks who use more primitive IDEs either by necessity or by choice, this is a great language feature.
Bug: After a subtle, undocumented change, a platform API no longer allows
nil strings. Wizard mysteriously crashed on OS X Mavericks when that operating system was first released. Why? Because a certain widget that displays strings underwent an imperceptible API change. Before Mavericks, if you passed
nil to the widget, the widget displayed nothing. (Sometimes I wanted to display nothing, in which case I passed
nil.) But with Mavericks, the widget unilaterally decided that the string argument was mandatory, and passing
nil caused an exception instead. Even when compiling on Mavericks, the compiler and the static analyzer were completely silent about this.
The Swift Fix: With Swift, strings are values, and values are either optional or they're not, and methods can say whether they accept optional values. So if we lived in a Swift world, the method definition of the widget would have had a way of saying, "Hey buddy, I no longer accept optional values," and I would have gotten a compile-time error instead of a flood of emails from angry Mavericks users.
Bug: I used a dictionary instead of a struct and mistyped the name of the key somewhere. So sue me, I just wanted a quick and dirty data container, and C structs don't play nicely with Core Foundation types, and I don't want a hundred methodless container classes with dumb names polluting my workspace. So I just used a dictionary like anyone who has ever used a scripting language would, and of course I typed
@"indxe" somewhere instead of
@"index" and something's not working quite right.
The Swift Fix: Structs are values and you can use them in collections. Yippee! No more 3-key dictionaries waiting to cause mayhem. Typing
indxe causes a compiler errror. As a bonus, Swift has generics, so a function can ask for an array containing only a particular kind of struct. In other words, Swift eliminates those "mystery arrays" and "mystery dictionaries" which weigh down on every Objective-C developer's soul.
Those are just the first examples that spring to mind — there are others like prohibiting uninitialized memory and out of bounds memory accesses, but you've probably seen stuff like that already in other languages that were designed anytime after the year 1990.
Swift is not the simplest of languages. There are many keywords that make assertions about different things, and there a number of rather arcane rules about when arrays are copied or not copied, which initializers are allowed to call which other initializers, how protocols inherit from other protocols, and so on. But I don't blame the language designers for the level of complexity — each of the language's features feels like it was designed to address a genuine problem in software engineering, all the while balancing programmer productivity, performance, and code maintainability.
Overall, as I was reading the Swift manual, I found myself mumbling "oh man" and "that's great" at all the things the Swift designers had done to help me write clean, bug-free code. I'll need to play around with Swift to know if it will be fast enough for all of my future application needs, but since it was designed by the same brain that brought us LLVM, I'm pretty optimistic about performance.
There is one design choice in particular for which I would like to commend the language designers — no garbage collection. Instead, Swift uses automatic reference counting, which takes a little extra work on the part of the programmer (in order to prevent strong reference cycles). But the benefit accrues to the user, in the form of a hiccup-free software experience. I'm sure that Swift will be marketed in terms of its benefits to software developers, but I think the real beneficiaries are Mac and iOS users, whose lives are destined to get just a tiny bit more predictable, and that much more pleasant.
That is, until they encounter Hecate: The Hex Editor From Hell.
You're reading evanmiller.org, a random collection of math, tech, and musings. If you enjoyed this, you might also like:
If you own a Mac, my desktop statistics software Wizard can help you analyze more data in less time and communicate discoveries visually without spending days struggling with pointless command syntax. Check it out!