Monday, October 6, 2014

Initial Thoughts about Swift

Back in June, Apple announced the new language platform, Swift. I took a brief look at it and then put it aside for the time being. I figured the early adopters could vet things out without me, run around in circles of hysteria for a bit.

Fast forward a few months, iOS 8 and Xcode 6 are both official now, no longer beta. I have a prototype app written in Objective-C, that it's time to kind of do version 2 of. Is now a good time to try and grab hold of the train and jump on? I don't know yet. I'm trying to keep an open mind. Here's a couple of thoughts so far...

Out of Date Information
One of the most difficult bits, is that a lot of the information out there on the web is already slightly (or very) obsolete. Much of the initial traffic generated after the announcement was quick from-the-cuff responses, often just there to generate clicks. Looking for really useful and helpful content, one still must filter through a lot of noise. Hopefully, with time, the ratio will tip in favor of the more useful.

I found this to be very true with the first batch of tutorials that were quick to hit the streets. Most are just so flat out trite, they don't really teach you anything. An app that is a little more than "Hello World" doesn't really teach you much. Furthermore, many of them have issues in their purported source code that prevent you from finishing if you can't figure out what's changed (a common example I saw was issues with the optionals mechanism).

In the end, I found a Tetris game tutorial that I was actually able to complete (Swiftris). As a tutorial it's OK, it has a fun flippant style, and it actually goes through a bit of stuff. And it distinguished itself by not being overly trivial and actually producing a working program. Most of the following thoughts were generated from this tutorial, as well as reading quite a bit of the Apple Swift Docs.

Replacing one Legacy with Another
Back when Craig Federighi announced Swift, one of the catch phrases was "Objective C without the C". Computer language historians will describe Objective-C as a somewhat unholy union of two very different languages: Smalltalk and C. While somewhat effective, it's a weird experience. Being accomplished at both Smalltalk and C, I can personally attest to Objective-C's weirdness. I often giggle when coding Objective-C. In an ideal world, you'd be thrilled at being able to leverage the best of both worlds. But it's usually the case that each is holding the other back in amusing or annoying ways.

So supposedly Apple ditched the C. It's a typed Object Oriented language with a syntax that us more C like than the Smalltalk keyword style. In the end, I'd say they ditched both, and it's just its own language.

But like Objective-C which always had to play fiddle to its C heritage, Swift plays fiddle too. You may see posts pitching things as better or innovative, but what I perceive often is "since we're still using the Cocoa runtime, we had to come up with something." So while C is gone. The Cocoa libraries and runtime are not. And ultimately, Swift has to bend to fit that model. Just like with Objective-C where I would giggle at how C would force something silly into the marriage, I find myself asking "why did they do that??" and usually the answer is "ah, because the Cocoa runtime forced their hand there."

The Law of Conservation of Ugly wins again.

Head Turning Paradigm
One of the things that messed with me at first, is that Swift function signatures are backwards. In C, a function signature/definition might look something like:

  float doSomething(int arg1, double arg2)

Or in a more abstract sense

  returnType functionName(typeQualifier1 argName1, typeQualifier2 argName2)

This is a pretty common pattern in many languages. But in Swift, there's a game of musical chairs that is played so that we end up with things in different order. The equivalent Swift variant is

  func doSomething(arg1: Int, arg2: double) -> float

And put abstractly

  func functionName(argName1:typeQualifier, argName2:typeQualifier2) -> returnType

I don't know how I feel about it. It's different, so it kind of feels fresh and new. OTOH, my brain has spent a lot of years learning how to scan the opposite order, where qualifiers precede what they annotate, rather than post cede them.

:, :, and :
One of the things that makes the C part of Objective-C annoying, is that C with its many years of evolution can often feel complex to parse. You have to look at the context to figure out what a given character does. However, the : character doesn't play to much of a role in C. While cleaning up use of other infix characters, Swift decided to celebrate the : character.

So far, I've counted at least three different uses of this character that I have to press the shift key for (Swift has relegated the easier to type semicolon to near nothingness, using it as a
multiple; statements; on; the; same; line; separator just as in Python).

The first, as shown above, is that it is used in function signatures to "attach" the type of an argument to the back side of it.

The second, is that it can be used when calling a function (or method). It looks subtly, similar to a keyword style invocation.

  Point(x: 4, y: 2)

Yes folks, Swift lets you type not only a comma separated argument list (C style) or a colon delineated keyword list interspersed with arguments (Smalltalk style), but you get to (must) do both! Type out the function name, the parens, the commas, the keywords, and the colons. It's like a politically correct function signature. It's so all inclusive.

What I find particularly disingenuous about the readability of this though, is that it undos what I just got used to. I had decided that : was how I attached annotating information to a keyword (e.g. the type), but here the annotating or qualifying element precedes it.

This is not a show stopper. But what it means is that your brain can't use a simple pattern match to put the pieces together.n You can't see a code and instantly know if you're looking at a function definition or call. Instead you have to parse the surrounding context to figure out what you're seeing.

The third use, is to indicate that a list (array) is not a list, it's a dictionary. Dictionaries and Lists both start and stop with the [ ] characters in Swift, and the elements are separated by commas. But to figure out whether it's a literal Dictionary or List, you'll have to peer inside of it, scanning it's contents to see if you can find a :. If you do find one, then you have a Dictionary. Then please scan back to the beginning to see if it all started with a [ or a (, so you can disambiguate whether it was a function call, or a dictionary.

Keep on open mind, I keep muttering to myself about this one. Maybe some zen unifying principle will befall me eventually, and I'll see the wisdom in the ambiguities.

Wrap, Unwrap, Ugh
Objective-C uses the nil message eating pattern. You can send messages to the nil object, and things don't blow up. It just silently does nothing. It's not really Objective-C per se, it's the implementation of the Objective-C runtime engine. And since that doesn't go away with Swift, they had to allow for that kind of thing with Swift. The solution is to support optional types.

  var TheAnswer:Int? = 42

That says that TheAnswer can be an Int or it can be a nil. Anytime I want to access it though, I have to know that I declared it with a ? and use a ! to get the value out. But if that bothers me too much, I can live a little dangerously and declare it as

  var TheAnswer:Int! = 42

This says that it must be an Int, but it recognizes that until I get it initialized it might not yet be, so I'll have to be careful.

This need to paper over the Objective-C/Cocoa patterns of nil, is one of those cases where I see the legacy as compromising the new. Maybe I'll be wrong and become a big fan of the optionals system. So far though, the compiler is constantly nagging me to add !'s or ?'s here and there. Sometimes, I don't understand entirely why. So I'm not sure it's a productivity winner for me at all yet. We'll see how the lay app developer of iOS apps deals with it.

Finally for now, with all this type goodness, and the improved completion and playground, I was surprised to find that if you highlight a chunk of Swift code and choose the Xcode Refactor menu option, you'll be rewarded with this wonderful message:

Hopefully, we'll see that go away as Apple continues to mainstream its new darling language.