Swift: A Solid Modern Imperative Language
Note 1: these are first impressions only – I’ve only spent a day really looking at the docs and playing with the XCode beta so I am probably mistaken about some stuff
Note 2: I am using a beta of XCode, and it has caused me some trouble (a mysterious service it starts keeps crashing, filling my HDD up with core files.) I would recommend waiting for the non-beta if I were you.
Apple recently announced the support of a new language targeted at the same application programming space as Objective C. It’s called Swift and it seems to me a very good summary of the features all modern imperative languages are striving for.
The last decade or so has seen a strong resurgence in functional programing evangelism. Languages like F#, Scala, Clojure and even Erlang for a while re-introduced to mainstream programmers high-level concepts that imperative programmers were largely unfamiliar with. A short experiment with a language supporting algebraic data types, type inference, higher order functions, closures, or the standard foundational map, reduce and fold functions will convince any programmer that their language would be far better off being more declarative.
For a comprehensive guide to the Swift language see the Swift tour.
I have wanted two write another iOS app for a while now, and so I’m thinking Swift may be the way forward for me there. To that end I’ve spent all this morning going through docs and messing with XCode to get a feel for the various idioms and coding styles it encourages…
Syntactic niceties
Swift is a very much streamlined language, and for low friction it seems to take a lot from F#. Like F#, a programmer can seemingly almost approach swift as a scripting language – the first line in your source file can be functioning application code, no boilerplate required! And the ‘playground’ concept is very familiar to anyone who has used Scala Workspaces or F# interactive mode.
The clarity of syntax is quite impressive – type inference introduces var
and let
common to many modern languages, and bracket-less control flow operations and optional semicolons make your code look a lot cleaner (and a bit like golang).
Structure types may be initialised in-line at the point of instantiation: val vga = VideoMode(width: 800, height: 600)
. Once you see this you think of course, why would it be otherwise?
Syntactically there is a lot of shorthand available for interacting with fundamental data types:
1 2 3 4 5 6 7 8 9 10 11 |
|
And anyone who loves Scala’s string interpolation operators will appreciate the ability to write println("hi, my age is \(me.age - 5)")
.
As a special treat, Swift also supports Objective-C style named parameters. This can make some functions arguments more clear when they have the same type:
1 2 3 4 5 6 |
|
OK perhaps that is not a great example, but I think the concept has a lot of merit.
Functional concepts
In addition to type inference and closures, Swift has obviously been checking out the Scala and F# and the like for ideas, much to its credit.
First, fret not because higher-order operations are all available to you, and included in the standard library are standard set of foundational functions you’d expect in a functional language such that it is possible to write var ys = map([1,2,3], {i in i * 2})
.
But one thing that seems quite interesting to me is the extended syntax available to enumerations (known as ‘associated types’) that make them almost seem like algebraic data types…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
…plus, if you add a new value (say, Rectangle) to the enumeration the area()
function will fail to compile, as the compiler will complain that the switch must be exhaustive. Take that scala!
Tuples can be pattern matched using placeholders, bound parameters and where clauses, which is a fairly awesome thing:
1 2 3 4 5 6 |
|
There is no true currying though of course it can be simulated by having functions return other functions – garbage collection + closures means that you can create generators along the lines of:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
On a side note, Scala’s currying leaves a lot to be desired, as does it’s support of ADTs – one must explicitly make structures a case class before you get functionality approaching an ADT.
Optional types are also supported in the library but also with nice syntactic sugar. The ?
operator defines an optional type (similar to C#) and also allows operations on that type to be optionally unwound. The !
operator forces unwinding, and causes an error if the optional type is not set.
Also, there is some fancy syntax for switching on an optional type:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Note: this doesn’t currently compile – the current XCode 6 beta does not compile the samples provided by the documentation. I’ll leave this here though because it still captures the intent of the optionals feature
Notice how the if`` resolves the expression as false because the
?“` operator did not resolve.
I haven’t even touched on a few other cool features like @lazy
annotation, generics, variadic parameters, or the myriad ways closures can be specified (it turns out {$0}
is a valid closure, with inferred argument and return value!)
OO niceties
I’ll describe some features based on where I find them most familiar from:
- C# –
struct
andclass
types. Classes are reference-counted (see below) while structs have value semantics (are destroyed automatically.) - C# – extensions and computed properties remind me of C# extension methods
- Objective-C – Automatic Reference Counting (ARC) provides a kind of semi-manual garbage collection. Essentially whenever you set a reference type to
nil
it will be collected. (The language also supports weak references.) This system is similar to usingshared_ptr
s in C++ in that you can end up with circular references, but unlike C++ there don’t seem to be any automatic scoping facilities that relinquish resources as they move out of scope. I might be wrong about this. - Objective-C – Swift supports the notion of protocols for polymorphic behaviour
- ? – Object identity can be compared (i.e., are these references to the same object?) using the
===
operator.
Does it go far enough?
In many ways this is a fairly conservative language – Swift is clean and nice to use, and I think would make a good replacement for Objective-C, but most other modern languages are focusing on higher level concepts that don’t seem to be getting a showing here.
The main thing that comes to mind is the lack of language features to help out with thread synchronisation and concurrency. Other languages are focusing on lightweight thread-like structures or coroutines, asynchronous actors or asynchronous computation expressions/monad type syntax (think F# async {}
.)
This is the first release of this language and I think some initial conservatism might be sensible. Typically I think compiled and C-based languages have preferred to put new functionality into libraries and only reluctantly add keywords and syntax to the existing base language. On the other hand, other languages (C# 5, F#, Haskell) have shown that without syntactic sugar (like async { }
, do { }
, yield
and the like) it is seemingly implausible to make async-friendly code look super readable and imperative, avoiding what is often known as callback hell.
So here’s hoping this project keeps the steam it’s started off with.
Do we need another language?
Swift is certainly more approachable than Objective-C, which I very much appreciate. Apple have always been quite good at providing an environment where different languages interoperate seamlessly, so there really seems no downside – if you have a lot invested in Objective-C you can still leverage all your previous work with Swift, or presumably use other peoples swift libraries in your own Objective-C applications.
There will always be curmudgeons of course, but they should be ignored. The lengths that some will go to to justify not having to learn new concepts is always amazing to me, especially when doing so is the best way to progress in our industry!
Apple takes the development of programming languages quite seriously. They are heading up some of the more interesting additions to new versions of C++, most anticipated (by me) being the ‘modules’ concept that promise to bring C++ compile times and binary interfaces in line with more modern high-level languages. They play this role of innovator well here because the concepts outlined in their proposal are drawn directly from practical experience in implementing said features in the Objective C language itself.