Swift 4: the Good, the Bad and the Lame

2017/12/04

How does Swift 4 stand against other popular languages? Should you use Kotlin or F# instead?

Good: Retroactive modeling

Very nice feature of Swift is that you can make a type to conform to a protocol even if you don’t have access to the source code of the type.

This is not possible with interfaces in Kotlin or F#.

Good: Tuples with named fields

Another very good thing about Swift is the possibility to name fields of tuples. This is especially useful when returning multiple values from functions:

func minMax(arr: [Double]) -> (min: Double, max: Double) {
    // ....
}

Kotlin and F# don’t support this. Instead you have to create a new type and assign it a name. Eg.:

type MinMaxResult = { Min: double; Max: double }

let minMax arr =
    // ....

Bad: Standard library is lacking

Let’s compare two programs which use regular expression to extract items from the string str. The first one is in Swift 4:

let regex = try! NSRegularExpression(pattern: "\\* ([a-z]+)(?: \\(([a-z]+)\\))?")
let str = """
    * first
    * second (blah)
"""

let matches = regex.matches(in: str, range: NSRange(str.startIndex..., in: str))

let nsStr = str as NSString
for m in matches {
    let title = nsStr.substring(with: m.range(at: 1))
    if m.range(at: 2).location != NSNotFound {
        let desc = nsStr.substring(with: m.range(at: 2))
        print("Item '\(title)' with description '\(desc)'")
    } else {
        print("Item '\(title)' without description")
    }
}

The second one is in F#:

let regex = Regex("\\* ([a-z]+)(?: \\(([a-z]+)\\))?")
let str = "
    * first
    * second (blah)
"

let matches = regex.Matches str

for m in matches do
    let title = m.Groups.[1].Value
    if m.Groups.[2].Success then
        let desc = m.Groups.[2].Value
        printfn "Item '%s' with description '%s'" title desc
    else
        printfn "Item '%s' without description" title

Although the programs do exactly the same thing the Swift program is longer.

One problem with Swift is that some classes exist in two variants. For example String and NSString or Range and NSRange. Another problem is that Swift is missing some very useful properties so instead of

m.Groups.[2].Success

you have to write

m.range(at: 2).location != NSNotFound

Similar problem can be shown in other situations like downloading data from the web, processing XML, working with files, etc.

Bad: No async support

Many modern programming languages have special support for coroutines. The main motivation is to simplify writing async code. With Swift 4 you have to manually split your async code into callbacks while Kotlin and F# compilers will do it for you.

Bad: Reference counting

The main point of garbage collection is to promote code reusability by lifting the duty to care about memory. With reference counting in Swift 4 you have to care about memory because you have to prevent reference cycles.

On top of that reference counting is usually much slower than other forms of garbage collection if you have enough free memory. Which is usually the case for most devices today. On the other hand having more memory won’t improve the performance of reference counting. You can see for yourself that some Swift programs in The Computer Language Benchmarks Game try to avoid reference counting by using UnsafeMutablePointer.

Memory management in Kotlin and F# is easier to use and it’s also usually faster.

Lame: Very slow compilation

Unfortunately Swift 4 can’t compile simple functions like this one:

func sanitizeString(s: String) -> String {
    return s.filter { (c) in
        Character("A")...Character("Z") ~= c ||
        Character("a")...Character("z") ~= c ||
        Character("0")...Character("9") ~= c ||
        " -,".contains(c)
    }
}

The code is correct but too complex for the Swift type checker. Here is the error message:

Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions

Conclusion

Swift 4 has some really nice features but they don’t cut it. You can write faster, shorter and more elegant code in Kotlin or F#. With Xamarin you can use F# to develop apps for Apple devices. And hopefully Kotlin/Native will soon bring Kotlin to iOS.