Handling Multiple Closure Parameters

So Natasha has a fair criticism about auto-completion1 in Xcode with regards to functions that take multiple closures and Swift's trailing closure syntax. I think there are many issues with auto-complete and Swift, but that's different rabbit hole to go down.

Instead, what I wanted to focus on was another way to solve the problem, which also helps with the auto-complete issue.

Here's the basic original problem:

func doSomething(value: Int, onSuccess: () -> (), onError: () -> ()) {
    if value == 0 {
        onSuccess()
    }
    else {
        onError()
    }
}

So instead of writing code in one the following ways (which all have the weird multiple closure issue):

doSomething(5, { println("success") }, { println("error") })
doSomething(0, { println("success") }) { println("error") }
doSomething(5, { println("success") }, { println("error") })

We can restructure the code using a very simple promise model.

struct CallbackResult<T> {
    let value: T
    let failed: Bool

    func onError(fn: (value: T) -> ()) -> CallbackResult<T> {
        if self.failed {
            fn(value: value)
        }

        return self
    }

    func onSuccess(fn: (value: T) -> ()) -> CallbackResult<T> {
        if !self.failed {
            fn(value: value)
        }

        return self
    }
}

func doSomething(value: Int) -> CallbackResult<Int> {
    return CallbackResult(value: value, failed: value != 0)
}

Then the usage becomes:

doSomething(10)
    .onSuccess { println("foo(\($0)): success") }
    .onError { println("foo(\($0)): error") }

doSomething(0)
    .onSuccess { println("foo(\($0)): success") }
    .onError { println("foo(\($0)): error") }

If you are familiar with JavaScript, you'll see a similar thing with deferred objects in jQuery and lots of other places as well.

There are lots of other benefits to this approach as well, such as helping flatten out async code that has a bunch of callbacks in it.

Anyhow, just another option.

  1. So I just realized that this was an old post of hers… auto-complete is still as terrible as ever though. Maybe one day.
Handling Multiple Closure Parameters

Swift Namespaces

I've seen some people complaining about the lack of namespaces in Swift… well, I'm not sure if I've seen this anywhere else, but you can fake namespaces if you really must.

enum std {
    static func add(x: Int, _ y: Int) -> Int { return x + y }

    enum more {
        static func sub(x: Int, _ y: Int) -> Int { return x - y }
    }

    struct apples {
        var count: Int;
    }
}

std.add(1, 2)
std.more.sub(1, 2)

var apples = std.apples(count: 12)
apples.count = 10

Now, I don't really recommend this, but it's kind of fun to hack around sometimes.

Update

Oh… and we can mimic using too:

typealias m = std.more
m.sub(1, 2)

I think you still need to have it qualified though, so no naked use of sub.

Swift Namespaces

Swift v1.2 β2 Performance

I've been taking a look at performance of Swift for a while now, with two very specific focus points:

  1. Developer workflow (non-optimized builds)
  2. Real-time applications (fully-optimized builds)

I'm very happy to report that Swift v1.2 β2 seems to have made some really great improvements in performance, even over Swift v1.2 β1.

Performance Numbers1

Language: C, Optimization: -O0                    ┃  6.3 β2  ┃  6.3 β1  ┃  6.1.1   ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━┩
RenderGradient (Pointer Math)                     │   38.651 │   38.266 │   38.780 │
──────────────────────────────────────────────────┴──────────┴──────────┴──────────┘

Language: C, Optimization: -Os                    ┃  6.3 β2  ┃  6.3 β1  ┃  6.1.1   ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━┩
RenderGradient (Pointer Math)                     │   10.374 │   10.042 │   10.162 │
──────────────────────────────────────────────────┴──────────┴──────────┴──────────┘

Language: C, Optimization: -Ofast                 ┃  6.3 β2  ┃  6.3 β1  ┃  6.1.1   ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━┩
RenderGradient (Pointer Math)                     │    3.112 │    3.022 │    2.976 │
──────────────────────────────────────────────────┴──────────┴──────────┴──────────┘

Language: Swift, Optimization: -Onone             ┃  6.3 β2  ┃  6.3 β1  ┃  6.1.1   ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━┩
RenderGradient ([Pixel])                          │ 3684.914 │ 4012.283 │ 29134.32 │
RenderGradient (UnsafeMutablePointer)             │ 171.3359 │ 162.9272 │ 152.2643 │
RenderGradient ([Pixel].withUnsafeMutablePointer) │ 386.9801 │ 523.7199 │ 1159.273 │
──────────────────────────────────────────────────┴──────────┴──────────┴──────────┘

Language: Swift, Optimization: -O                 ┃  6.3 β2  ┃  6.3 β1  ┃  6.1.1   ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━┩
RenderGradient ([Pixel])                          │ 26.91437 │ 46.57198 │ 66.40995 │
RenderGradient (UnsafeMutablePointer)             │ 22.71384 │ 21.74668 │ 22.21477 │
RenderGradient ([Pixel].withUnsafeMutablePointer) │ 22.33094 │ 39.78517 │ 39.62590 │
──────────────────────────────────────────────────┴──────────┴──────────┴──────────┘

Language: Swift, Optimization: -Ounchecked        ┃  6.3 β2  ┃  6.3 β1  ┃  6.1.1   ┃
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━┩
RenderGradient ([Pixel])                          │ 19.66853 │ 40.28331 │ 66.04476 │
RenderGradient (UnsafeMutablePointer)             │ 20.02236 │ 19.53774 │ 19.51404 │
RenderGradient ([Pixel].withUnsafeMutablePointer) │ 20.25013 │ 41.26989 │ 38.34509 │
──────────────────────────────────────────────────┴──────────┴──────────┴──────────┘

This is great! The worst case, [Pixel], in non-optimized builds was 29s back in Xcode 6.1.1 (the latest official build). In latest beta, that's down to 3.6s! Sure, that's still a horribly slow time, but that's still a massive improvement.

The other thing to note is that nearly all of the optimized builds got twice as fast as before. The biggest thing to note here is that the usage of arrays is now just as good in optimized builds as the pointer versions. That's a big win for code clarity. Once the debug performance of arrays is fully addressed, this will be even better.

Hopefully 6.3 β3 shows just as remarkable improvements.

Also, I've started a GitHub repo to start tracking this stuff better:

https://github.com/owensd/swift-perf.

Feel free to send any pull requests for items you'd like to see tracked here. I do plan on doing some updates to the infrastructure piece of it to get some easier delta reporting.

  1. The times should be read as: "the amount of time, in milliseconds, it took to compute 30 iterations".
Swift v1.2 β2 Performance

Swift’s Protocol Extension

I have been working on porting over my ObjC platform layer from

Handmade Hero and I have a bit of code that looks like this:

self.aboutMenuItem.title = [self.aboutMenuItem.title
                            stringByReplacingOccurrencesOfString:DEADZONE_TITLE
                            withString:APP_NAME];
self.hideMenuItem.title = [self.hideMenuItem.title
                           stringByReplacingOccurrencesOfString:DEADZONE_TITLE
                           withString:APP_NAME];
self.quitMenuItem.title = [self.quitMenuItem.title
                           stringByReplacingOccurrencesOfString:DEADZONE_TITLE
                           withString:APP_NAME];
self.helpMenuItem.title = [self.helpMenuItem.title
                           stringByReplacingOccurrencesOfString:DEADZONE_TITLE
                           withString:APP_NAME];
self.window.title = [self.window.title
                     stringByReplacingOccurrencesOfString:DEADZONE_TITLE
                     withString:APP_NAME];

The point of this code is to go through and replace all of the text with the

target name in it to a string defined by a config file. But you can easily

imagine that this is any code that is starting to look fairly redundant across

a set of various differently typed items.

This is really just a simple case of iterating over the items in the collection and calling the title setting.

for (var item) in items {
    item.title = item.title.replace(placeholder, withString: title)
}

The astute readers out there may have caught an issue with this approach though. For one, a window is of type NSWindow and the other items are of type

NSMenuItem. That's not going to work as they share no base class that contains a title property.

We have two choices here:

  1. Handle window on it's own separate line, or 2. Create a protocol extension so they do have a common interface with a title

property.

I want my code to capture the intent as much as possible with as little redundancies as possible, so option #1 is out.

So, let's think about option #2. What I really want to say is that both

NSWindow and NSMenuItem share a common set of behaviors, or more specifically in this case, a single behavior: title.

Now, it seems that they actually already do share this behavior and that it is just not codified. However, if you look at the declaration of each, you'll notice that NSWindow actually returns a String? for title and NSMenuItem returns a String (note the optional vs. non-optional difference).

Ok… that's annoying, but we can work around that!

protocol HasTitle {
    var ht_title: String { get set }
}

extension NSMenuItem: HasTitle {
    var ht_title: String {
        get { return self.title }
        set { self.title = newValue }
    }
}

extension NSWindow : HasTitle {
    var ht_title: String {
        get { return self.title ?? "" }
        set { self.title = newValue }
    }
}

With the protocol extension HasTitle, we have now codified what the behavior semantics are. It's then trivial to implement that appropriately for each type that you want to share this HasTitle codification.

The final code to make use of this now looks like:

let items: [HasTitle] = [aboutItem, hideItem, quitItem, helpItem, window]
for (var item) in items {
    item.ht_title = item.ht_title.replace(placeholder, withString: title)
}

I almost forgot… you'll probably paste this code in and wonder why it is not

working for you. I've created an extension on String that adds the replace

function. It simply forwards the parameters into

stringByReplacingOccurrencesOfString.

Now, unfortunately, Swift needed a little bit of type annotation help to make it all work 100%, but we've done it. With one simple protocol and two easy class extensions, our usage code has become significantly cleaner, easier to update, and less error prone.

Could we bring this technique back to ObjC? Of course. Just write the simple for-loop to begin with. However, you'll probably stop there because that is all that is needed to make the ObjC side happy as we can send messages to any object instance; we can completely forgo the HasTitle protocol.

However, that is the part that I think it vastly more important as it's that protocol that leads us into thinking about better composition models. I hope to do a longer blog post about that at another time.

Happy Swifting!

Update, February 16th: I removed the usage1 of map as it was an abuse of the function. I used it because I didn't want to use the ugly version of the for-loop and I was having issues with the iterative version. Turns out I just need (var item) instead of var item. Seems like a compiler bug to me…

  1. Ok… it was really a very bad abuse of the map() function.
Swift’s Protocol Extension

Swift v1.2 Performance

In a series of posts I wrote a few weeks back, I looked at the performance of Swift in the context of debug (e.g. non-optimized) builds. The developer workflow pain that I was having was significant.

Of course, today a new build of Xcode dropped that finally (I jest a little) contained a new build of Swift: Swift v.1.2.

So, is it any better?

I've spent about ten minutes playing around with my projects (described in the blog posts mentioned above). I ran into the following issues:

  • Xcode crashed opening a source file (/sigh)
  • Swift v1.2 conversion missed updating two cases:
  • Byte was removed and not automatically changed to UInt8 in the

    initializer case.

  • UnsafeMutablePointer<Pixel>.null() was not replaced to it's proper usage:

    let pixels: UnsafeMutablePointer<Pixel> = nil.

The crash was annoying. However, the Swift conversion process went well and I don't really care that they missed those two cases.

So…?

SO MUCH BETTER!! BUT…

The ObjC optimized RenderWeirdGradient() function looked like this:

void RenderGradient(RenderBufferRef buffer, int offsetX, int offsetY)
{
    int width = buffer->width + offsetX;
    int height = buffer->height + offsetY;
    uint32_t *pixel = (uint32_t *)&buffer->pixels[0];

    for (int y = offsetY; y < height; ++y) {
        for (int x = offsetX; x < width; ++x) {
            *pixel = 0xFF << 24 | (x & 0xFF) << 16 | (y & 0xFF) << 8;
            ++pixel;
        }
    }
}

The timings I saw on my machine here:

-O0   0.038723s
-Os   0.010972s

I tested against three different Swift loops:

Raw UnsafeMutablePointer

func RenderGradient(var buffer: RenderBuffer, offsetX: Int, offsetY: Int)
{
    var offset = 0
    for (var y = 0, height = buffer.height; y < height; ++y) {
        for (var x = 0, width = buffer.width; x < width; ++x) {
            let pixel = Pixel(
                red: 0,
                green: UInt8((y + offsetY) & 0xFF),
                blue: UInt8((x + offsetX) & 0xFF),
                alpha: 0xFF)
            buffer.pixels[offset] = pixel;
            ++offset;
        }
    }
}

Pixel Array

func RenderGradient(inout buffer: RenderBuffer, offsetX: Int, offsetY: Int)
{
    // I truly hope you have turned down the number of iterations or you have picked
    // up a new build of Swift where this is not dog slow with -Onone.
    var offset = 0
    for (var y = 0, height = buffer.height; y < height; ++y) {
        for (var x = 0, width = buffer.width; x < width; ++x) {
            let pixel = Pixel(
                red: 0,
                green: UInt8((y + offsetY) & 0xFF),
                blue: UInt8((x + offsetX) & 0xFF),
                alpha: 0xFF)
            buffer.pixels[offset] = pixel;
            ++offset;
        }
    }
}

Pixel Array with UnsafeMutablePointer

func RenderGradient(inout buffer: RenderBuffer, offsetX: Int, offsetY: Int)
{
    buffer.pixels.withUnsafeMutableBufferPointer { (inout p: UnsafeMutableBufferPointer<Pixel>) -> () in
        var offset = 0
        for (var y = 0, height = buffer.height; y < height; ++y) {
            for (var x = 0, width = buffer.width; x < width; ++x) {
                let pixel = Pixel(
                    red: 0,
                    green: UInt8((y + offsetY) & 0xFF),
                    blue: UInt8((x + offsetX) & 0xFF),
                    alpha: 0xFF)
                p[offset] = pixel
                ++offset;
            }
        }
    }
}

With -Onone, the timings are (the diff % is compared against the optimized ObjC code presented above):

Swift v1
Swift Rendering Tests: 30 iterations per test
---------------------
UnsafeMutablePointer<Pixel>     avg time: 0.186799s
[Pixel]                         avg time: 27.9754s
[Pixel].unsafeMutablePointer()  avg time: 1.18535s
Swift v1.2
Swift Rendering Tests: 30 iterations per test
---------------------
UnsafeMutablePointer<Pixel>     avg time: 0.185078s, stddev: 0.00442746s, diff: -377%
[Pixel]                         avg time: 3.92371s, stddev: 0.0777589s, diff: -10032%
[Pixel].unsafeMutablePointer()  avg time: 0.518955s, stddev: 0.00921328s, diff: -1239%

With -O, the timings are:

Swift v1
Swift Rendering Tests: 30 iterations per test
---------------------
UnsafeMutablePointer<Pixel>     avg time: 0.0223397s
[Pixel]                         avg time: 0.0287606s
[Pixel].unsafeMutablePointer()  avg time: 0.0402743s
Swift v1.2
Swift Rendering Tests: 30 iterations per test
---------------------
UnsafeMutablePointer<Pixel>     avg time: 0.022574s, stddev: 0.00115951s, diff: -105%
[Pixel]                         avg time: 0.0268918s, stddev: 0.00143757s, diff: -144%
[Pixel].unsafeMutablePointer()  avg time: 0.0414112s, stddev: 0.00207772s, diff: -276%

There are few large takeaways here:

  1. The raw UnsafeMutablePointer<Pixel> is still significantly faster, in all

scenarios; no performance change between Swift versions. 2. The [Pixel] has significantly better performance than before. It seems

the optimized build even got slightly faster. HOWEVER, the array solution

is still not good enough as it can only render at about 7 to 8Hz (target is

30Hz). 3. Keeping the [Pixel] array and using the unsafeMutablePointer() call for

"hot areas" of your code has also gotten much better. It now gets us to the

target 30Hz in non-optimized builds, but still nearly 3x slower than

simply using an UnsafeMutablePointer<Pixel> to begin with.

My key takeaway:

Swift is getting better and faster but it's still not suitable in the domain

space I'm currently working in for this project: high-performance, real-time

systems.

Eagerly awaiting Swift vNext!

Swift v1.2 Performance

Swift, Protocols, and Composition

Ash Furrow wrote up this post yesterday: http://ashfurrow.com/blog/protocols-and-swift/. It's a good post, you should read it. The problem he outlines is this:

"Here's the problem: you have two types that want to talk to each other."

Ash's solution to the problem was to use protocols to essentially turn the problem inside out. His solution definitely works and it's better than his original way of doing it. It did get me thinking about solving the same problem in maybe a slightly more flexible way.

The drawback with Ash's solution, in my opinion, is that it still takes a heavy leaning on an object-oriented paradigm. I don't think we need that, especially in this case.

If we break down the problem into parts, I think we end up with this:

  1. A set of nutritional information (calories and hydration level). 2. Types of food (wet and dry) that can affect that nutritional information. 3. An animal type (cat) that has a set of nutritional information and the

ability to eat food.

The issue with the object-oriented approach is that it coupled the notion of eating with the animal type (see the eat extension). I don't think we really want that. Instead, we want to capture the relationship between food and nutrition through some eat function.

Let's setup the types:

enum Food {
    case Dry(caloriesPerGram: Double)
    case Wet(caloriesPerGram: Double, hydrationPerGram: Double)
}

protocol Nutrition {
    var calorieCount: Double { get set }
    var hydrationLevel: Double { get set }
}

struct Cat: Nutrition {
    var calorieCount: Double = 0
    var hydrationLevel: Double = 0
}

Ok, so what do we have:

  • The Food type is an enum because we have clear restrictions on the type of

food available and how it impacts Nutrition.

  • The Nutrition item is a protocol that defines the data that it needs. This

is done because we are saying that a cat "has a" set of nutrition information.

  • The Cat is simply a data type that is made up of Nutrition data.

The last thing we are missing is the ability to eat. If you are thinking about objects then I think the obvious thing to do is to add an eat function on

Nutrition. There is another approach though: thinking instead about the transformations of the data.

Because I care more about transforming data, I'm going to create a top-level function eat:

func eat(var nutrition: Nutrition, food: Food, grams: Double) -> Nutrition {
    switch food {
    case let .Dry(caloriesPerGram):
        nutrition.calorieCount += caloriesPerGram * grams
    case let .Wet(caloriesPerGram, hydrationPerGram):
        nutrition.calorieCount += caloriesPerGram * grams
        nutrition.hydrationLevel += hydrationPerGram * grams
    }

    return nutrition
}

func eat<T: Nutrition>(nutrition: T, food: Food, grams: Double) -> T {
    return eat(nutrition, food, grams) as T
}

There are a few things to note:

  1. The var usage in the parameter list just let's us get a copy of that

parameter and use it locally as a new variable. 2. There is absolutely no coupling with any of the types that could possibly

contain Nutrition information. 3. There is a generic version so we do not have to cast when dealing with

concrete implementations of Nutrition, such as Cat.

The usage of the code looks like this:

let kibble = Food.Dry(caloriesPerGram: 40)
let fancyFeast = Food.Wet(caloriesPerGram: 80, hydrationPerGram: 0.2)

var dave = Cat()
dave = eat(dave, kibble, 30)
dave = eat(dave, fancyFeast, 20)

And then we can do some other more functional oriented operations a bit more naturally:

let cats = [Cat(), Cat(), Cat(), Cat(), Cat(), Cat(), Cat()]
let caloriesEatenByCats = reduce(map(cats) { cat in
    eat(cat, kibble, 30) }, 0) { sum, cat in
        sum + cat.calorieCount }

But here is where the really nice part of this choice comes along: if I want to add a Dog type, I only need to create the struct for it I'm done.

struct Dog: Nutrition {
    var calorieCount: Double = 0
    var hydrationLevel: Double = 0
}

let dogs = [Dog(), Dog(), Dog(), Dog()]
let caloriesEatenByDogs = reduce(map(dogs) { dog in
    eat(dog, kibble, 30) }, 0) { sum, dog in
        sum + dog.calorieCount }

In Ash's implementation, you have to then go add an eat function on each new type you are dealing with. We lose no flexility either because if a Dog is supposed to eat differently, we can just create an overload for it.

The other nice part is we can mix and match our Nutrition types like this:

let animals: [Nutrition] = [Dog(), Cat()]
let caloriesEatenByAnimals = reduce(map(animals) { animal in
    eat(animal, kibble, 30) }, 0) { sum, animal in
        sum + animal.calorieCount }

It's just another way of thinking about the problem. Swift seems to be a language that values immutability and composition over mutability and if we start to think about solving problems that way, I think we end up with more solutions like I presented where it's really just about how we manipulate the data in composable ways.

Source: https://gist.github.com/owensd/7bda3f7b3f91245e3542

Swift, Protocols, and Composition