Archive for the ‘Swift’ Category

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:

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.

Buy a book: Swift Style

esswiftscaled

I’m happy to announce that Swift Style has gone into beta release at  the Pragmatic Bookshelf. My book is now ready for sale as part of their beta program. This program gives you early access to the book’s material as I work on it.

Be part of the writing process. Beta access enables you to offer feedback as I finish writing:

Before a book gets to the final, ready-to-publish state, it normally looks quite rough. It will have hundreds of typos and grammatical errors. It’s likely to have technical errors that would normally get corrected in a final read-through by reviewers. And it’ll certainly look fairly ugly—we don’t do any layout work until just prior to sending a book to the printer, so there will be widows, orphans, text split across page turns and so on.

As you find mistakes or technical errors, if want to argue for or against a style rule, or you’d like to submit an enhancement suggestion,  click the Report Erratum link on the book’s home page. If you have any in-depth feedback (either positive or negative) that goes beyond the scope of the erratum page, drop me an email. Enable notifications so you receive an email whenever the book updates.

Swift Style: Beta Book

Self-Published Books

Thank you for your support!

Enter the Python: Peeking at a language

Last week, I wrote about how I set up Xcode to run Python. It’s been working great. Xcode may not be everyone’s cup of tea, but I love it. Syntax highlighting, familiar keybindings, symbol completion. I couldn’t be happier. A lot of people pushed me to use Pycharm community edition, but while I’ve installed it and tried it a few times, I keep going back to Xcode. Warts and all.

I haven’t logged many hours in Python but it’s been a fascinating language experience. Let me go all metaphor on you. Way back in the 90’s there was this show called “Sliders“, about a bunch of people moving between parallel worlds. Almost everything was the same from world to world — normal humans, trees, buildings, whatever — but there were always fundamental differences in the culture and the people that always reminded you that you weren’t home.

Python is the Sliders version of Swift, the one where Chris Lattner was never born. Everything is eerily familiar and nothing is quite right. Where are my value types? My generics? My type extensions. Let me throw out another metaphor — one that will probably resonate with even fewer people: Python is the language version of the Nethack Rogue Level, where you enter “what seems to be an older, more primitive world.” It’s all familiar. Nothing is exactly the same.

This morning, I attempted to extend a type. I’m working with Anki’s Cozmo robot SDK, which is written for Python 3.5.1 or later. I’m trying to reconfigure many of the basic calls into more appropriate chunks suitable for teaching kids some programming basics.

Instead of focusing on asynchronous callbacks and exceptions, I want to provide really simple blocks that extend the robot type API in a way that hides nearly all the implementation details. I’m trying to build, in a way, a Python version of Swift Playgrounds but with a real robot. (And it’s going well, but more about that in another post.)

What I found was that Python really doesn’t want to extend types. You can subclass. You can compose. But so far, I haven’t found a way to add an extension that services an existing type. When I asked around, the Python gurus on freenode recommended I stop worrying about polluting the global namespace and embrace freestanding functions as needed.

Oh, my delicate Swift sensibilities! Adding global functions and constants? Cluttering the global namespace? I find myself clinging to Swift conventions. I create enumerations and type my arguments:

class Direction(IntEnum):
    '''Permitted driving directions.'''
    forward = 1
    backward = -1

def drive(robot: cozmo.robot.Robot, 
    direction: Direction = Direction.forward): ...

The Cozmo SDK defines its constants like this:

LEFT = 1
RIGHT = 2
TOP = 4
BOTTOM = 8

I don’t think I’m in Swift-land anymore.

A lot of the things I like most about Python appear to be fairly new, like that ability to type arguments. I’m assured by some Pythonistas that this is almost entirely syntactic sugar, and there appears to be no type-checking, inference, or casting applied to calls.

I thought I would really hate the indentation-based scoping but I don’t. It’s easy to use (start a scope with a colon, indent 4 spaces for that scope). It reads well. It’s clean. Non-braced scoping ended up being a complete non-issue for me, and I mildly admire its clean look.

I’m less excited by Python’s take on structured documentation. The standard is outlined in PEP-257. Unlike Apple’s Swift Documentation Markup, Python markup doesn’t seem to support specific in-line tool use in addition to document generation. I’m sensitive to how much better Swift creates a structured system for detailing parameters, error conditions, return types, and descriptions, and how it scales from types to functions and methods to individual instances and provides Xcode integration.

So much in Python is very similar to Swift but with a slight twist to it. Closures? Lambdas are in there. Mapping? That’s there too. Partial application? Seems to be. Most times that I reach for a tool in my existing proficiencies, I can usually find a Python equivalent such as list comprehension, which is basically mapping across sequences and collections.

I’m sorely missing my value types. One of the first things I did when trying to work through some tutorials was to try to create a skeleton dictionary rather than type out full dictionaries for each instance. I quickly learned Python uses reference types:

# the original dict was more complicated
studentDict = {"name" : "", "tests" : []} 

joe = studentDict # create joe
joe["name"] = "joe"
bob = studentDict # create bob
bob["name"] = "bob"

# reference type
print(joe) # {'tests': [], 'name': 'bob'}
print(bob) # {'tests': [], 'name': 'bob'}

Oops.

In any case, I’m still really really new to the language given my full-court-press on finishing Swift Style. As much as I wish I were writing this code in Swift, I’m glad that I have the opportunity to explore Python and hope I get to spend some time with Scala in the near future. This project is offering me a lot of valuable insights about where Swift came from and increased appreciation for the work the core Swift team put in to give us the language we have now.

Swift Holy Wars: To bracket or not in option sets?

As much as I’d like OptionSets to be a type, they’re not.

public protocol OptionSet : SetAlgebra, RawRepresentable

The current implementation (via a protocol), enables API evolution. As Joe Groff pointed out to me, developers can break down a single option into multiple refined options, while still offering the original components. You can see an example of this in the following implementation, where the compound energyStar and gentleStar  options occupy an equal footing with  component bit-shifted flags:

public struct LaundryOptions: OptionSet {
    public static let lowWater = LaundryOptions(rawValue: 1 << 0)
    public static let lowHeat = LaundryOptions(rawValue: 1 << 1)
    public static let gentleCycle = LaundryOptions(rawValue: 1 << 2)
    public static let tumbleDry = LaundryOptions(rawValue: 1 << 3)
    
    public static let energyStar: LaundryOptions = [.lowWater, .lowHeat]
    public static let gentleStar: LaundryOptions = [.energyStar, .gentleCycle]
    
    public init(rawValue: Int) {
        self.rawValue = rawValue
    }
    public var rawValue: Int
}

Although this design looks like you are using sets, you really aren’t.  The square bracket syntax is a bit a of a cheat:

let options1: LaundryOptions = [.lowWater, .lowHeat]
let options2: LaundryOptions = .energyStar
let options3: LaundryOptions = [.energyStar, .lowHeat]

// prints 3 for each one
[options1, options2, options3].forEach {
    print($0.rawValue)
}

When you surround an option set with brackets, you get back an option set. This means in Swift, [.foo] is the same as .foo.

I entered into a heated style debate today with Soroush Khanlou over option sets, specifically if it were better to make a call like accessQueue.sync(flags: [.barrier]) using or omitting the brackets.

Soroush felt that omitting the brackets produces less noise. If you can compile without the brackets, why include them?

I said “use ’em”. When you’re passing flags and a static member, let the role guide your style. When the code expects an option set, make the argument look like an option set.

The brackets clearly indicate both the argument role and creates an affordance, a specific visual indication that you can expand the set by introducing more options. Without brackets, this may not be intuitively obvious to someone less familiar with option sets.

So what do you think? Brackets? No brackets? What Swift cuisine reigns supreme?

Holy Wars: Namespacing Hygiene

sssilver writes: “In my company I find code that’s basically a class with a bunch of static functions in it. When I ask people why not just write the functions directly, they answer that they don’t wanna pollute the namespace. In something like Rust, everything is scoped to the module. What’s the idiomatic way to do this in Swift?

Swift prefers namespacing to freestanding functions and constants. This applies even in module APIs where you gain a basic level of namespacing for free. You want to keep your namespace clean and focused, scoping items to types and protocols of natural interest.

This practice makes Swift a bit more hierarchical than you might be used to. In Swift prefer to:

  • Namespace constants into a type where they naturally fit.
  • Namespace functions into the types and protocols they service, either as static methods or by removing the first argument and re-implementing the function as an instance method.
  • Add subtypes rather than pollute the global namespace with items that are only of interest within a parent type. Subtypes allow the parent and its nested types to reduce complexity when referring to each other, so Shape.Triangle and Shape.Circle see each other as Triangle and Circle.
  • Embed functions that will only be called by a single method client into that method, rather than create a second method that exists only to serve one parent.
  • Move operator implementations into the types they service, so you reduce the number of operators implemented in the global namespace.

Where you might have previously created public constants and functions like these, now prefer to incorporate them into existing or utility types:

public let π = CGFloat(Double.pi) // no
public let τ = π * 2.0 // no

public func halt() { // no
    PlaygroundPage.current.finishExecution()
}

extension CGFloat { 
    /// The pi constant, yes
    public static let (pi, π) = (CGFloat(Double.pi), CGFloat(Double.pi))
 
    /// The tau constant, yes
    public static let (tau, τ) = (2 * pi, 2 * pi)
}

extension PlaygroundPage {
    // This is never going to be beautiful
    public static func halt() {
        current.finishExecution()
    }
}

Embedding globals into types as static members provides clean, Swiftier namespacing, with minimal overhead costs. Where possible, prefer extending an Apple-supplied type (like `CGFloat` and `PlaygroundPage`) over creating new types (like `MathConstants` or `PlaygroundRuntimeSupport`).

At the same time, don’t force constants and functions into classes where they have no natural fit. If you must create a new type to warehouse a namespace, prefer a no-case enumeration, which is guaranteed to be unconstructable.

I’ll probably think of more things after I hit “Publish” on this, so if I missed anything, let me know and I’ll update the post.