Checking into Swift

July 14, 2014

In the interest of learning Swift, I undertook one of the exercises catalogued on codekata.com—“Data Munging,” involving some simple file parsing. The first thing I learned? Regular expressions in Swift, which are really just Objective-C regular expressions at this stage, are remarkably unintuitive. I come from JavaScript, where regex literals and uncomplicated functionality make using regular expressions a breeze. Here is a sample of some data CodeKata asked me to parse:

       Team            P     W    L   D    F      A     Pts    1. Arsenal         38    26   9   3    79  -  36    87    2. Liverpool       38    24   8   6    67  -  30    80    3. Manchester_U    38    24   5   9    87  -  45    77

Assuming I go through the data line by line, I might use the following JavaScript to calculate the difference between goals for (column F) and goals against (column A):

var re = /\. (\w+) .* (\d+) - (\d+)/ for (var i = 0; lines[i]; i++) {     var matches = lines[i].match(re)     if (matches) {         var spread = Math.abs(parseInt(matches[2]) - parseInt(matches[3]))     }}

Here is my implementation in Swift of the same approach to this problem:

let re = NSRegularExpression(pattern: "\\. (\\w+) .* (\\d+) - (\\d+)", options: nil, error: nil) for line in lines {     let match = re.firstMatchInString(line, options: NSMatchingOptions.ReportProgress, range: NSMakeRange(0, countElements(line)))     if match?.numberOfRanges {         var startIndex = advance(line.startIndex, match.rangeAtIndex(2).location)         var endIndex = advance(line.startIndex, match.rangeAtIndex(2).location + match.rangeAtIndex(2).length)                 let goalsFor = line.substringWithRange(Range(start: startIndex, end: endIndex)).toInt()!                 startIndex = advance(line.startIndex, match.rangeAtIndex(3).location)         endIndex = advance(line.startIndex, match.rangeAtIndex(3).location + match.rangeAtIndex(3).length)                 let goalsAgainst = line.substringWithRange(Range(start: startIndex, end: endIndex)).toInt()!                 let spread = abs(goalsFor - goalsAgainst)     } }

Due to some incompatibilities between the type of range the Objective-C library returns and the type of range Swift uses for its String class, implementing this approach produces some very ugly code. My hope is that as time progresses, Apple will implement replacement libraries in Swift that will provide for more elegant solutions. That isn’t to say that elegant, useful code is currently beyond reach, as David Owens has documented here and here in his adventures working with JSON in Swift.

Swift isn’t all bad, of course. Generics, closures, tuples, and many other features borrowed from other languages are surefire crowd-pleasers. My favorite features focus on ways to write more concise code: operator functions and subscripts. Consider Ruby’s string multiplication:

secret_code = "Andrew rules! " * 42 # -> a string consisting of "Andrew rules! " 42 times

Granted, there aren’t many obvious uses for production code, but I get a kick out of it. I wrote a function in JavaScript to achieve the same effect on a previous project; however, I was denied the satisfaction of overloading the multiplication operator. Not so in Swift:

@infix func * (left: String, right: Int) -> String {     var result = ""    for (var i = 0; i < right; i++) {         result += left     }         return result } let secretCode = "Andrew rules! " * 42 // -> a string consisting of "Andrew rules! " 42 times

Swift allows developers to add infix, prefix, postfix, assignment, equivalence, and even custom operators. If your heart so desires, define an operator that is an arbitrary number of | characters. Sure, that example is rather obscene, but I value the fact that I could do that if it ever truly made sense. The Swift book offers no words on the possible abuses of operator functions.

operator infix ~|^<>^|~ {} // Implementation left as an exercise for the reader's imagination 4 ~|^<>^|~ 5 // Summons Cthulhu

Defining custom operators, and overloading standard ones, can lead to some heated discussions. I posted a few implementations of string multiplication on StackOverflow’s Code Review site, curious what sort of responses I would get. As of this writing, the only answer angrily, wholly decries the use of operator overloading. Admittedly, the commenter raises valid concerns over legibility and maintainability; custom operators won’t always be the best answer. In the Swift book, Apple smartly introduced the feature using a Vector2D class, a mathematical concept for which multiplication, addition and other basic arithmetical functions make sense to implement.

Having read through the Swift book, I realize that this post explores a small area of the exposed chunk of the iceberg that Apple hopes app developers will love and come to think of as home. I enjoy working in Swift, noting the limited space I have explored so far. Apple has laid an attractive, modern foundation with Swift that I think will support many solid applications in the future. I’ve written a small app in Swift, so look forward to a post on that process.