Swift Idioms

Over time, Swift has developed a distinct dialect, a set of core idioms that distinguish it from other languages. Many new developers now arrive not just from Objective-C but also from Ruby, Java, Python, and more. The other day, I was helping Nicholas T Chambers find his groove with the new language. He was porting some Ruby code to build up his basic language skills. The code he was working with was this:

def find_common(collection)
    sorted = {}
    most = [0,0]

    for item in collection do
        if not sorted.key? item then
            sorted[item] = 0
        end

        sorted[item] += 1

        if most[1] < sorted[item] then
            most[0] = item
            most[1] = sorted[item]
        end
    end

    return most
end

And his most recent Swift attempt was this:

func find_common(items: [Int]) -> [Int] {
    var sorted = [Int: Int]()
    var most = [0, 0]

    for item in items {
        if sorted[item] == nil {
            sorted[item] = 0
        }

        sorted[item]! += 1

        if most[1] < sorted[item]! {
            most[0] = item
            most[1] = sorted[item]!
        }
    }

    return most
}

Other than a couple of forced unwraps, there’s almost no difference between the two.  I  don’t know much Ruby but this code in both versions feels very C-like and non-functional (in the fp sense, not the “won’t work” sense).

I know Ruby supports some kind of reduce functionality, which you don’t see here. One of the first things I did when trying to learn Swift was to implement pages and pages of Ruby functional calls. I still have endless select, reject, delete_if, keep_if, etc playgrounds around. They’re really great for focusing in on learning the Swift language.

Here’s the rewrite I suggested:

import Foundation

extension Array where Element: Hashable {
    /// Returns most popular member of the array
    ///
    /// - SeeAlso: https://en.wikipedia.org/wiki/Mode_(statistics)
    ///
    func mode() -> (item: Element?, count: Int) {
        let countedSet = NSCountedSet(array: self)
        let counts = countedSet.objectEnumerator()
            .map({ (item: $0 as? Element, count: countedSet.count(for: $0)) })
        return counts.reduce((item: nil, count: 0), {
            return ($0.count > $1.count) ? $0 : $1
        })
    }
    
}

In a way, this is an unfair refactor because I “went there” with NSCountedSet but writing in Swift doesn’t mean you reject Foundation. It seems to me that a counted set is exactly the kind of thing this code was trying to do: “Say you have a list of a random type (but its the same type throughout), in an arbitrary order. how do you find the most common item in the list?“.

Here are some thoughts about the refactor

Leverage Libraries. When migrating Swift, consider whether Foundation and Swift Foundation types will get you there faster. Counted sets provide a good match here because they do all the work of grouping and counting members. I wish there were a native version as I’m not crazy about either the object enumerator or that the code will compile even if you don’t specify hashable elements.

Embrace Generics. The challenge list uses a random type. Hardcoding Int isn’t the way to do that. Bring generics into the solution early once you recognize the functionality is applicable to many types.

Consider Protocols. A native version of counted set would be Hashable at a minimum, just like Swift sets.  I include the restriction here but it does compile and run without that conformance.

Live Functionally. Any kind of “find this within a list” screams functional programming to me. If your variables exist to store intermediate state while iterating a list, look to Swift’s core map/filter/reduce fp calls and eliminate explicit state.

Avoid Global Functions. I felt my implementation was better expressed as a collection extension than a freestanding function. A mode always describes and operates on an array. Its implementation belongs as part of Array. I even considered making it a property rather than a function because a list’s mode is an intrinsic quality of an array. I’m still wavering back and forth on that point.

Think Tests and Documentation. Even before you write a single line of code, considering test cases and documentation has become a core part of Swift development. I added a little doc markup here, I didn’t add any tests.

Prefer Good Swiftsmanship. At first, I was drawn to syntactic specifics, like “use conditional binding” and “type the variable/prefer a literal” before I stepped back and considered the larger picture. Once I took a few moments to think about it, I retargeted my advice towards fp, but that doesn’t mean core Swift best practices should be overlooked.

A lot of this falls into the big picture little picture dichotomy. When learning Swift, you probably want to work from the details up: learning how optionals work and how to use them right and how to use fp, all the way to creating tests, documentation, and leveraging protocols and generics. It’s hard to get hit in the face with so many concerns at once.

Adding core API knowledge on top of *that* makes things even more difficult. Navigating both utility types and Cocoa/Cocoa Touch APIs represent a significant challenge to those new to Apple platforms, even for people with strong backgrounds in modern language fundamentals.

At this point, writing “Swiftily” doesn’t just mean using conventional coding idioms but also remembering and leveraging the platform the language is arriving from. I hope counted set (and many other Cocoa Foundation outliers) make it over the bridge to native inclusion.

Safe Programming: Optionals and Hackintoshes

Here’s a doozy of an outlier case where conditional binding could  have saved a user experience for an otherwise unhappy consumer. I recently talked with a developer whose production code mixed forced unwraps with a guaranteed API. I wasn’t sure whether to tag this post as Holy War. As you’ll discover, this isn’t your run of the mill development situation.

The deployed-code crashes occurred while querying Apple’s smart battery interface on a Hackintosh. Since the laptop in question wasn’t an actual Apple platform, it used a simulated AppleSmartBatteryManager interface rather than the Real Thing™. In this case, the simulated manager didn’t publish the full suite of values normally guaranteed by the manager’s API.

The developer’s API-driven contract assumptions meant that forced unwraps broke his app for that user:

Since IOKit just gives you back dictionaries, a missing key, is well… not there, and nil. you know how well Swift likes nils…

Applications normally can’t plan for, anticipate, or provide workarounds for code running on unofficial platforms. There are too many unforeseen factors that cannot be incorporated into realistic code that ships.

Adopting a universal style of conditional binding enables you to “guide the landing” on unexpected failures, including those failures that occur under less exotic circumstances. Conditional binding lets you introduce a user-facing “bad stuff happened” alert, like the following example:

guard let value = dict[guaranteedKey] 
    else {
        alertUser("Functionality compromised when unwrapping " +
            "Apple Smart Battery Dictionary values. Skipping this " +
            "feature. Please file a bug with full platform info, etc..")
        return
}

Contrast the preceding “safe landing” approach with the more common approaches demonstrated in the following snippet:

// Crash, angry user, bad reviews
let value: String! = dict[guaranteedKey] // or
let value: String = dict[guaranteedKey]!

Prefer a style that establishes a positive pathway for both recovery and user support. Providing fallbacks and user-facing alerts even when your assumptions are guaranteed to be correct  is a always positive coding style.

Universal conditional binding reduces the overhead involved in  debugging unexpected Black Swan deployments and allows you to respond with “Sorry pal, my software is only guaranteed to work on official platforms. No refunds.” This practice  adds robustness and assumes that in reality bad execution can happen for the oddest of reasons.

Like my posts? Buy a book. Swift Style is available now via Pragmatic Programmer’s Beta Program.

Don’t attempt tech conversations after anesthesia

Does anyone know if I need to capture self as weak in a UIView.animation block?

Once I was afraid. I was petrified. Scared I couldn’t render without view at my side. Then I spent so many nights thinking how you did me wrong, and I referenced strong, and I learned how to pass my ARC along…

And now you’re back from @nonescape. I just walked in to find you here with that sad look upon your face.

I should have made you dereference, should have made you leave your key, if I’d known for just one second, you’d need to be released

Go on now, walk out the door. I’m not the same calling instance, you’re not needed anymore

Weren’t you the one who tried to create a reference cycle with goodbye, do you think I’d crumble, deallocate and die?

My value will survive!

Cue Sax solo.

p.s. you want self to live throughout the animation and possibly into completion. stay strong.

Apple Swift team undergoes reorganization

Statement from Chris Lattner:

Since Apple launched Swift at WWDC 2014, the Swift team has worked closely with our developer community.  When we made Swift open source and launched Swift.org we put a lot of effort into defining a strong community structure.  This structure has enabled Apple and the amazingly vibrant Swift community to work together to evolve Swift into a powerful, mature language powering software used by hundreds of millions of people.

I’m happy to announce that Ted Kremenek will be taking over for me as “Project Lead” for the Swift project, managing the administrative and leadership responsibility for Swift.org.  This recognizes the incredible effort he has already been putting into the project, and reflects a decision I’ve made to leave Apple later this month to pursue an opportunity in another space.  This decision wasn’t made lightly, and I want you all to know that I’m still completely committed to Swift.  I plan to remain an active member of the Swift Core Team, as well as a contributor to the swift-evolution mailing list.

Working with many phenomenal teams at Apple to launch Swift has been a unique life experience.  Apple is a truly amazing place to be able to assemble the skills, imagination, and discipline to pull something like this off.  Swift is in great shape today, and Swift 4 will be a really strong release with Ted as the Project Lead.

Note that this isn’t a change to the structure – just to who sits in which role – so we don’t expect it to impact day-to-day operations in the Swift Core Team in any significant way.  Ted and I wanted to let you know what is happening as a part of our commitment to keeping the structure of Swift.org transparent to our community.

-Chris

The Swift project is driven by a core team of Apple engineers:

The core team “reviews and helps iterate on language evolution proposals from the community at large, acting as the approver of these proposals. Team members help drive Swift forward in a coherent direction consistent with the goal of creating the best possible general purpose programming language.” They are appointed by the project lead.

Holy War: Type aliases

Kyle Cardoza writes: Erica, Is it considered bad style to typealias OpaquePointer when you have to deal with OpaquePointer values that point to different types? The typealiases make the code read so much nicer…

Using typealiases to create “pseudotypes” (where typealiases essentially duplicate a single  type) neatly organizes your code. I endorse any solution that emphasizes semantics and supports readability. As OpaquePointer is not generic, it doesn’t encapsulate type information the way Array<Int> or Set<String> do:

// Both are typed to OpaquePointer, so nothing concrete
// distinguishes the two roles.
// let p1 = OpaquePointer(unsafeMutableRawPtr1)
// let p2 = OpaquePointer(unsafeMutableRawPtr2)

Building convenience typealiases emphasizes the distinction between otherwise structurally identical uses. This differentiates each use-point and provides built-in “type commentary”:

typealias OpaqueType1Pointer = OpaquePointer
typealias OpaqueType2Pointer = OpaquePointer

let p1: OpaqueType1Pointer = OpaquePointer(rawPtr1)
let p2: OpaqueType2Pointer = OpaquePointer(rawPtr2)

// or, thanks Nil, directly:

let p1 = OpaqueType1Pointer(rawPtr1) 
let p2 = OpaqueType2Pointer(rawPtr2)

You might consider an alternative. If you’re willing to trade off a little overhead against enhanced type safety, you might introduce a simple value type. Wrapping the opaque pointer enables you to use a type-specific initializer. Here’s an extremely rough example of what that might look like:

struct SometypeWrapper {
    let opaque: OpaquePointer
    init(value: Sometype) {
        opaque = OpaquePointer(Unmanaged
            .passRetained(value).toOpaque())
    }
}

What do you think? Good use of type aliases? Bad? Or should you always go with a wrapper? Let me know. Drop a note in the comments or send over a tweet.

Thanks, Mike Ash

Forced Unwrapping URLs

Let me start with a little background. Laptopmini wanted to know why this code wasn’t compiling. Admittedly, Swift’s error messages leave room for improvement. The tl;dr was: he needed to swap the 2nd and 3rd lines of code. This allows both properties to be initialized before the code refers to self.


I immediately fixated on those exclamation points. “Are there any circumstances that these URLs will fail during creation? And if so, don’t you want to control that crash?” Laptop pointed out that there was no circumstance where his URLs would be malformed, and it was perfectly safe to use the exclamation point.

Despite this, his approach bugged my aesthetics. There’s no reason those URLs should be created in that initializer. I figured there were better ways to deal with this, moving URL creation out of the initializer and controlling crash landings with better error messages.

First, I considered extending URL to offer a safer non-optional initializer. The following snippet offers “controlled descent”, providing valuable feedback for any string that cannot be used to construct a URL.

extension URL {
    /// Non-optional initializer with better fail output
    public init(safeString string: String) {
        guard let instance = URL(string: string) else {
            fatalError("Unconstructable URL: \(string)")
        }
        self = instance
    }
}

This seemed too big a hammer for this problem. Instead, I decided to recommend the same approach with a solution localized to the SocketEndPoint type:

// Returns `URL` with guided fail
public enum SocketEndPoint: String {
    case events = "http://nowhere.com/events"
    case live = "http://nowhere.com/live"
    
    public var url: URL {
        guard let url = URL(string: self.rawValue) else {
            fatalError("Unconstructable URL: \(self.rawValue)")
        }
        return url
    }
}

This approach allows his init code to simplify. Under the updated design, it uses ordinary URLs in the initializer and no exclamation points.

// His initializer
fileprivate init() {
    self.eventSocket = WebSocket(url: SocketEndPoint.events.url))
    self.liveSocket = WebSocket(url: SocketEndPoint.live.url))
    self.eventSocket.delegate = self
    self.liveSocket.delegate = self
}

Long story short:

  • String enumerations are handy but SocketEndPoint wasn’t pulling its weight. Its job is to deliver named URLs. It should do that no matter however the type is implemented.  Don’t let types slack off because there’s an “almost there” solution baked into the language.
  • Keep initializers clean and simple.
  • When weighing a universal solution against a simple local one, sometimes it’s best to think small and fix the problem in the immediate context.
  • I considered normal URL construction (returning an Optional) and creating a WebSocket initializer with implicitly unwrapped optionals (public init(url: URL!)This approach offered no real advantages and lost the ability to report which string was malformed. Also, ugly.

You can see a few of approaches I kicked around at this gist.

Dear Erica: Singletons and Static Property Side Effects

Laptopmini writes, “Can you define a ‘get‘ closure for a singleton’s sharedInstance? I have a web socket manager and I’d like it to call ‘connect()‘ any time its instance is fetched”

A basic Swift singleton looks like this:

public final class Singleton {
    public static let shared = Singleton()
    private init() { }
}

This design creates a class with a single accessible shared instance. The class is marked final, and the initializer is private, ensuring the type cannot be subclassed or instantiated beyond shared.

To introduce side effects, create indirect access to the singleton and add your custom behavior to a getter:

public final class Singleton {
    private static let _shared = Singleton()
    private init() { }
    
    public static var shared: Singleton {
        get {
            print("side effects here")
            connect() // for example
            return _shared
        }
    }
}

This works but it’s a little more complicated than it has to be. As a get-only property, you can omit the get syntax. Just move the custom behavior to the top-level var clause, as in the following modification:

public final class Singleton {
    private static let _shared = Singleton()
    private init() { }
    
    public static var shared: Singleton {
        print("side effects here")
        connect() // for example
        return _shared
    }
}

Quick summary:

  • Use reference types for singletons.
  • Mark the type final, the instance public, and the initializer private.
  • When naming, prefer the Swiftier shared to the more Objective-C sharedInstance.
  • Create a static getter for any side effects.
  • Omit the get syntax for get-only properties.

Have some thoughts about improving this? As always, drop a note in the comments or tweet me and I’ll tweak.

Rob N has a good point here:

Swift Style vs ProseLint: The Smackdown

ProseLint is great. As I’m writing a book about style and linting, it’s natural to try to lint the book that lints your programming. In using this tool, I’ve encountered some amusing “lint fails” that I’d thought I’d share.

ProseLint vs Nil Coalescing: “hyperbolic.misc ‘`??`’ is hyperbolic.” Winner: Swift Style.

ProseLint vs discussion of Forced Unwwrapping: “leonard.exclamation.30ppm More than 30 ppm of exclamations. Keep them under control.” Winner: ProseLint. Any forced unwrapping, even in a discussion about forced unwrapping, is an obvious fail. Save the kittens, drop the !’s.

ProseLint vs Meaningful Variable Names: “typography.symbols.multiplication_symbol Use the multiplication symbol ×, not the letter x” Winner: Swift Style. As Freud said, sometimes an letter  “x”  is just a letter “x”. (Or was that Groucho Marx? I forget.)

ProseLint vs “Use American English Spelling” rule: “consistency.spelling Inconsistent spelling of ‘color’ (vs. ‘colour’)” Winner: Swift Style. When writing for a global audience, prefer “color” to “colour”. (See? I did it again. — B. Spears)

Winner? Forget the points. It’s ProseLint. This summary doesn’t include the great catches made and fixed, like excessive use of “very”, repeated word detection, etc. Great tool, check it out.

Reducing to Swift sets

A friend asked me, “Is there a better way to reduce to a set than .reduce (Set<String>()) { $0.union(CollectionOfOne($1)) } ?” He was fetching results from an external source and wanting to feed them into a set.

We kicked some ideas back and forth about how this could be implemented. Would he need to query the set before fetching all the items (no) and would his data set be so large that it would be impractical to store the intermediate results into an array before creating a set (also no).

I built a suite of tests, trying out his reduce method, using normal insertion, etc.  I assumed that using a Set initializer would probably be the best approach for a pre-computed array, but it turns out that union and insertion performed better in repeated tests:

timetest("initializer") { //  0.652348856034223
    var x: Set<String> = []
    (1 ... 5_000).forEach { _ in
        x = Set(letters)
    }
}

timetest("union") { // 0.524669112986885
    var x: Set<String> = []
    (1 ... 5_000).forEach { _ in
        x = x.union(letters)
    }
}

timetest("insert") { // 0.572339564969297
    var x: Set<String> = []
    (1 ... 5_000).forEach { _ in
        x = []
        letters.forEach ({ x.insert($0) })
    }
}

timetest("reduce") { //  0.762973523989785
    (1 ... 5_000).forEach { _ in
        var x = letters.reduce(Set<String>()) {
            $0.union(CollectionOfOne($1))
        }
    }
}

That surprised me since you’d imagine that  init<Source : Sequence where Source.Iterator.Element == Element>(_ sequence: Source) and func union<S : Sequence where S.Iterator.Element == Element>(_ other: S) -> Set<Element> would have similar performance characteristics.

What didn’t surprise me was that trying to create a set on the go cost more than storing intermediate results to an array and then building a set out of them. So long as the array was reasonably limited in size (that is large enough to be non-trivial but not so large that it put a burden on application memory), an intermediate array seems to be the better approach. Set(collectedResults) outperformed insert, formUnion, and reduce/union for non-trivial result sizes.

Unexpected precedence issues with try? and as?

Tim Vermeulen recently wrote on the Swift Evolution list that try? precedence can be unexpected:

if let int = try? mightReturnInt() as? Int {
 print(int) // => Optional(3)
}

Specifically, he discovered that try?’s precedence is lower than as?’s precedence, so you may have to add parentheses to get the right result.

if let int = (try? mightReturnInt()) as? Int {
    print(int) // => 3
}

He also found a similar issue with using try? on a throwing-optional-returning scenario:

if let int = try? mightReturnInt() {
    print(int) // => Optional(3)
}

if let int = (try? mightReturnInt()) ?? nil {
    print(int) // => 3
}

There’s some magic baked into if let item = item as? T that automatically lifts optionals, which doesn’t yet seem to extend to try?. If you’re running into these situations, consider adding parentheses and nil-coalescing as demonstrated in these examples.

In case you think a throwing-optional scenario is too “out there”, think of a file system request that would throw on an unreadable directory and return nil if a specific file does not exist. Although obscure, it is not unthinkable to combine the two approaches.