Archive for July, 2015

Ask Erica: How do Enums synthesize ErrorType

JSCardwell4: “Any idea how the enum cases are accessed to synthesize their ‘_code’ property for objective-c consumption? I fiddled with the current state of reflection and mirrors a few weeks ago to try and create extension defaults for my ‘Enumerable’ protocol so I wouldn’t have to keep adding the property … enum WhatUp: Enumerable { case Nuthin, WholeLottaNuthin; static var all: [Whatup] { return [.Nuthin, .WholeLottaNuthin] } } After reading that the compiler synthesizes the bridged NSError to include a ‘code’ value equal to an enum ErrorType case position, I began wondering if their might be a way to retrieve this kind of thing or if it is some kind of compiler magic with the parsed source code.”

I am of course guessing but I suspect there’s a default implementation for ErrorType where Hashable that produces _code; the _domain is just a string of the parent type. If you know better, please give me a heads up.

enum Error : ErrorType {case NoError, Unlucky}

print(Error.NoError._code) // hash value 0
print(Error.Unlucky._code) // hash value 1
print(Error.NoError._domain) // String of Enumeration, "Error"

Genericizing Code

Here are a few points to keep in mind that I just threw together and would love some feedback on.

Prefer functionality over implementation. Protocols tell you what a construct does and not how it does it. Focus your code on the connections between data creation and data consumption instead of the particulars of specific types.

It’s never too late to refactor. While it’s great to write generics and protocols right out of the box, it’s extremely common to develop code and then consider how to retrofit.

Watch out for repeated code across different types. Repeated code segments with just a few type-specific changes hints at patterns that lend themselves to generic and protocol implementations. Focus on the commonalities of design patterns to find targets of opportunity.

One protocol does not rule them all. Keep your protocols short, sweet, and meaningful. Each one should be a noun (often ending with “Type”) or a verb (ending with “ible” or “able”). Think this is this a kind of thing and this can do this. Avoid overloading protocols with too many semantics that distract from a protocol’s one true calling.

Differentiate type constraints from parameter constraints. Refactor functions with extensive angle bracket clauses to use protocol extensions and methods. Swift 2.0’s protocol extensions use where clauses to constrain where methods apply, enabling you to move those type constraint clauses away overloaded angle-brackets and into a more meaningful context.

Conform at the highest possible level. When adding protocol conformance and default implementations, do so at the highest possible abstraction that still makes sense. Instead of adding separate adoptions for, for example, Int and String, check whether there is a unifying concept that can be introduced at a common protocol they both already adopt. If this becomes too general, create a new protocol, conform the types that apply, and maybe even add an extension to implement the generic behavior you’re looking for.

Design with collections in mind. Differentiate whether you will work with heterogeneous (same protocol) or homogeneous (same type) functions and design your protocols correspondingly. Self requirements enable you to add same-type constraints. Protocol names support common conformance.

Nils vs Throws in #swiftlang Part II

Yesterday, I posted about when to use nil and when to use throw when working with Swift 2.0. I suggested avoiding nil as a semaphore, that is don’t use nil to signal an error state. Swift 2.0’s new system includes simple ErrorType enumerations and do/try/catch.

These enable you to better represent distinct error conditions compared to naked nils and to handle situations where you’d normally leave a scope and report an error. Error handling simplifies return types to avoid optionals and unwrapping in failure situations.

I warn you I got very little sleep last night so the following info will probably be incoherent.

Read On…

Nil vs throws #swiftlang

It is tempting to use optionals to signal when an operation has failed. The following snippet represents Swift prior to 2.0 and is common to Apple’s traditional Cocoa patterns. An unsuccessful operation returns nil, a successful one returns a value.

func doSomething() -> String? {
   let success = (arc4random_uniform(2) == 1) // flip a coin
   if success {return "success"} // succeed
   return nil // fail
}

if let result = doSomething() {
   // use result here
}

Starting in Swift 2.0, reserve this approach for initialization and prefer guard over if-let. Instead of using optionals as semaphores, that is to indicate success and fail conditions, use Swift’s new error handling system.

func betterDoSomething() throws -> String {
   let success = (arc4random_uniform(2) == 1) // flip a coin
   if success {return "success"} // succeed
   throw Error.failure // fail
}

do {
   let result = try betterDoSomething()
} catch {print(error)}

This refactoring skips optionals; the nil-case is never of interest to the client code. Swift 2.0 error-handling means you never have to unwrap.

This one change profoundly affects Cocoa-sourced APIs. Calls that used NSError pointers pre-Swift 2.0 change their return type from optional to non-optional, add the throws keyword, and eliminate error pointers from API calls. The new system works sends NSError through do-try-catch.

// Old
func dataFromRange(range: NSRange,
   documentAttributes dict: [NSObject : AnyObject],
   error: NSErrorPointer) -> NSData?

// New
func dataFromRange(range: NSRange,
   documentAttributes dict: [String : AnyObject]) throws -> NSData

By introducing error handling, optionals can eliminate their overloaded “failed call” semantics. It’s always better to use throws with well-defined errors than to use optional semaphores. When you really have no information to pass back to the caller other than “I failed”, Swift 2.0’s updated error system simplifies creating an error enumeration to explain why that failure occurred. It is ridiculously easy to add informative errors that don’t require complicated NSError initializers to construct.

enum Error: ErrorType {case BadData, MemoryGlitch, ItIsFriday}

Although many current APIs, especially those based on Core Foundation calls, have yet to transition to the new system, I encourage you to update your code to avoid using optionals as semaphores. Return your optionals to the “contains a value or does not contain a value” semantics they were designed to handle.

I’m working on the Swift Developer’s Cookbook for Pearson/Addison Wesley. Send me your questions and thanks for buying my books!

Xcode: Searching with Regex

I’m asked about this on a surprisingly regular basis and Xcode keeps changing the way it handles things. Here’s the scoop for the latest version of Xcode 7 Beta:

1. The search-bar’s Find Options are found under the pop-up from the magnifying glass at the left.

Screen Shot 2015-07-27 at 12.15.13 PM

2. Choose Regex or Text from the Matching Style pop-up.

XcodeScreenSnapz001

3. The prompt text updates to show your current match style, in this case Regex. Options at the bottom also enable you to match case (leave unchecked for case insensitive searches) and wrap searches.

Screen Shot 2015-07-27 at 12.06.22 PM

4. When doing text searches, you can specialize for contains, starts-with, matches, and ends-with.

XcodeScreenSnapz002

Parameter-less subscripting fun in #swiftlang

Lily Ballard recently discovered that Swift enables you to implement zero-argument subscripting. I’m writing about protocols today, so I thought I’d kick the wheels a little and see if I could create a monstrous use-case similar to my postfix printing fun I wrote about last year.

Like that implementation, this one passes-through its value, so printing becomes a simple side effect.

Beta 4: We want more! #swiftlang

Just a few quick notes of interest

Falling in love with indirect enums. You can declare a single case indirect or the entire enum as a whole. Still a few fiddly bits. Trying to do the pattern match / variable binding in an if statement kills the compiler.

enum List<T> {
    case Nil
    indirect case Cons(head: T, tail: List<T>)

    func dumpIt() {
        switch self {
            case .Cons(head: let car, tail: let cdr):
                print(car); cdr.dumpIt()
            default: break
        }
 
       // Fail, die, Signal Abort trap 6
       // if case .Cons(head: let car, tail: let cdr) = self {
       //     print(car); cdr.dumpIt()
       // }
    }
}

// Construct a list and dump it
var node = List<Int>.Nil
for value in [1, 2, 3, 4, 5] {
 node = List.Cons(head: value, tail: node)
}
node.dumpIt()

The very odd single-uple thing where you could refer to something by .0 is now gone. The ability to refer to the “0” element of a scalar value (producing the scalar value itself) has been removed. (17963034)

SinkType and SinkOf are now gone. RIP.

Extensible collections are folded into Range-replaceable, and there are some nice new default implementations.

You can now use “performSelector“! Well, to a point. You have to descend from NSObject, but hey, why not?

// Sorry, not going to work here
extension Int {func plus1()->Int {return self + 1}}

// IntClass does not have a member named performSelector
// unless you descend from NSObject
class IntClass : NSObject {
    var value : Int = 0
    func plus1() {value = value + 1}
}

//let z = 5.performSelector(Selector("plus1"))
//print(z) // DIES!

let w = IntClass(); w.value = 5
w.performSelector(Selector("plus1"))
print(w.value) // prints 6, works

Throws annotation is now official  Swift documentation comments recognize a top-level list item – Throws: … which should be used to document what errors can be thrown and why. These appear alongside parameters and return descriptions in Xcode’s QuickHelp. (21621679)

You can now conform to protocols that are “less available than the type itself”, so a class that’s available from say iOS 6 can conform to a protocol that’s specific to iOS 9.

Mirrors are messed up. Total redesign and far less functionality plus lots and lots of bugs. I’ll worry about this next week but right now don’t expect anything to work the way it did or you might expect it to. For example, mirrors of scalars seem to lack a simple “.value” option.

func ExploreItem(item: Any) {
    func ExploreItem_(item: Any, indent: Int) {
        let mirror = Mirror(reflecting: item)
        print(String(count: indent, repeatedValue: Character(" ")), appendNewline:false)
        print("\(mirror.description) : \(mirror.subjectType)", appendNewline:false)
        if mirror.displayStyle != nil {
            print("[\(mirror.displayStyle)]", appendNewline: false)}
        let count = mirror.children.count
        if count != 0 {
            print(" \(count) children", appendNewline:false)}
        print("")
        if count == 0 {
            print(String(count: indent + 4, repeatedValue: Character(" ")), appendNewline:false)
            print("- \(item)")
       }
       for child in mirror.children {
           print(String(count: indent + 4, repeatedValue: Character(" ")), appendNewline:false)
           let label = child.label ?? "??"
            print("- \(label): \(child.value)")
       }
    }
 
    print("---------------------")
    print("Exploring \(item)")
    print("---------------------")
    dump(item)
    ExploreItem_(item, indent: 0)
}

More as I find it.