BENEDIKT TERHECHTE

This is my research notebook. I'm an OSX / iOS indie developer. After 8 years of Objective-C I really enjoy Swift nowadays. Trying to publish all my research on Development, Swift & other technologies here.

Wed, 30 Sep 2015 #

Getting your iPhone 6s Chip Foundry from Swift

Here's a small Github project by WUD which uses the private libMobileGestalt to identify the manufacturer of the CPU in your fancy new iPhone 6S. Because, as you may not know, this year Apple is sourcing the chips from two different foundries: Samsung and TSMC. So which one did you get? You could, of course, just run the aforementioned GitHub project on your phone. However, that's all Objective-C and out of curiosity I wondered: How would you pull that off in Swift?

1 Step One: Adding a header

The first obstacle is already a tricky one. LibMobileGestalt doesn't offer a header as it is a private library. So how do you tell Swift / the linker that the function you want to call will indeed exist at compile time. At first glance it seems that pure Swift doesn't offer any facilities for this (if you're impatient, there's another solution below ;-), so we can always resort back to the Bridging Header that Apple introduced to easily bridge the Swift and the Objective-C/C worlds. Here is a short guide on how to add a bridging header to your project. Basically add a new header file, and add the path to your target's Build Settings under Objective-C Bridging Header.

Then, add the following code to your header:

#if __cplusplus
extern "C" {
#endif
    CFPropertyListRef MGCopyAnswer(CFStringRef property);
#if __cplusplus
}
#endif

But what if you're writing a pure Swift project and don't want to add a bridging header? There's a mostly undocumented (Thanks to someone on HN for pointing it out to me) Swift attribute called @asmname that allows us to do something similar straight in Swift. Russ Bishop has a post on this and much more you can do in this realm.

Using the @asmname keyword, the code looks like this (and you can remove the bridging header):

@asmname("MGCopyAnswer")
func MGCopyAnswer(_: CFStringRef) -> Optional<Unmanaged<CFPropertyListRef>>;

We're basically telling Swift that this function exists, and we're telling it specifically what it requires and what it will return.

2 Step Two: Writing Swift

Next up, we want to write the Swift code to call this function, so let's do it:

chipInfo = MGCopyAnswer("HardwarePlatform")

We might expect that the result of this is already the required String, but Swift is a safe language so first of all it is returning an Optional here, since the key in question ("HardwarePlatform") might not even exist. We first have to get the value out. To do that, we'll use the new Swift 2 guard statement.

guard let chipInfo = MGCopyAnswer("HardwarePlatform")
    else { fatalError("Could not read hardware") }

If we look at the type of chipInfo, sadly, we still don't have a String. Instead, we're getting Unmanaged<CFPropertyList>. What's that?

The Apple Documentation has this to say about Unmanaged:

A type for propagating an unmanaged object reference.

When you use this type, you become partially responsible for keeping the object alive.

Of course, we're getting a value from the Core Foundation world where ARC does not know how to manage the memory. Objective-C uses the __bridge keyword to manage this, and in Swift it smartly changes the type so that we definitely don't forget that this variable's memory is currently not managed. NSHipster, and Apple have more documentation for this. What we'll do is call the takeRetainedValue method:

guard let chipInfo = MGCopyAnswer("HardwarePlatform")
    else { fatalError("Could not read hardware") }
chipInfo.takeRetainedValue()

So, do we finally have a String? No, but we're close. We're getting a CFPropertyList object back. The Apple Documentation has this to say about this type:

CFPropertyListRef can be a reference to any of the property list objects: CFData, CFString, CFArray, CFDictionary, CFDate, CFBoolean, and CFNumber.

This means that if the result is indeed of type CFString, since CFString is toll-free-bridged to NSString and since NSString is bridged to Swift's String, we could just force cast this to the String type and be done with it. Swift is a safe language however, and when possible we should strive to do everything the safe way. So instead we'll do an optional cast to String and if that works out, we can get the actual String value out of the Optional.

If we do it this way, it will not blow up whtn the contents of the reference are, say, a CFDate or a CFBoolean. This is particularly easy with Swift's Pattern Matching syntax:

guard let chipInfo = MGCopyAnswer("HardwarePlatform")
    else { fatalError("Could not read hardware") }

switch chipInfo.takeRetainedValue() as? String {
case "s8000"?:
    print("Samsung")
case "s8003"?:
    print("TSMC")
default:
    print("Unknown")
}

The question mark at the end of the two codes ("s8000"?) signifies that we're not matching against a String, but against an Optional<String>.

3 Step Three: Add the Framework

There we are. Awesome it works. Except, it doesn't. You still have to add the libMobileGestalt.tbd library and the Core Foundation framework to your project target's Linked Frameworks and Libraries.

I've also created a small GitHub project that includes all this including the correct library setup etc.

If you read this far, you should follow me (@terhechte)
on Twitter


    Tue, 25 Aug 2015 #

    Optional throw via try? in Swift 2 beta 6

    This post is also available in 🇨🇳Chinese Thanks to SwiftGG

    Swift 2.0 b6 includes a new way of handling exceptions via the try? keyword. This is a quick post to explain the basics, and why this is cool.

    In Swift 1.x, all we had for error handling were optionals and NSError. Which is why many people adopted Either / Result types as they can be found in other programming languages:

    let success = Result<String, NSError>.Success("success")
    

    With Swift 2 and the introduction of try / catch exception handling. Internally, this doesn't use expensive stack unwinding, as other (say, Objective-C or Java) do it, but instead seems to pretty much return something akin to Either or Result. Only the syntax hides this from the user in order to make it simpler to use1.

    1 Swift 2 b5 and earlier

    However, once you start using the new do / try / catch more, what happens from time to time is that you start nesting code into messy branches because do is (was) incompatible with the other major way of handling potentially unknown states: optionals. Here's a particular ugly piece of code. Observe how we're nesting if let with let with do with let 2.

    import Foundation
    // get the currently logged in user
    func loggedInUser() -> Int? { return 0 }
    // get his name
    func getUserName (userId: Int) throws -> String { return "Claus" }
    // create a new image post with this username. Returns the post data
    func imagePostForUserName(name: String, imageURL: NSURL?) -> NSData? { return NSData() }
    // post the data to a server
    func postImage(data: NSData) throws -> Bool { return true }
    
    if let uid = loggedInUser() {
        do {
    	let username = try getUserName(uid)
    	if let data = imagePostForUserName(username, imageURL: nil) {
    	    do {
    		let success = try postImage(data)
    		if success {
    		    print ("Submitted")
    		}  
    	    } catch {
    		// more error handling
    	    }
    	}
        } catch {
    	// todo: error handling
        }
    }
    

    One reason why this is difficult to simplify is that the do forces a break in any multi guard or multi let 3.

    2 Swift 2 b6

    With beta 6, we get a new keyword, try? which performs a throwing operation and returns optional None in case of failure and optional Some in case of success. Quoting straight from the changelog:

    A new keyword 'try?' has been added to Swift. 'try?' attempts to perform an operation that may throw. If the operation succeeds, the result is wrapped in an optional; if it fails (I.e. if an error is thrown), the result is 'nil' and the error is discarded. ‘try?’ is particularly useful when used in conjunction with “if let” and “guard”.

    This makes it possible to retrieve the value of a potential throwing operation as an optional. If we apply this to our code above, we can simplify it quite a bit:

    if let uid = loggedInUser(),
       username = try? getUserName(uid),
       data = imagePostForUserName(username, imageURL: nil),
       success = try? postImage(data)
       where success == true {
          print ("Submitted")
    }
    
    Submitted
    

    This is, of course a bit of a contrived example, engineered to explain try?. But still, that's definitely less code. We're, of course, loosing a lot of possibly valuable error information that would otherwise be available in the catch.

    3 Which to choose?

    try? can help you write terser code at the expense of loosing insights. Using try? only returns an optional without further information on the particular cause of the error / exception. The benefit, of course, is beautiful composability with a lot of the other Swift syntax, like map, flatmap, switch, guard, if let, for case, and others.

    The non-optional try works great for distinct task where you're not dependant on earlier or later possible optional results.

    The aforementioned Result type, on the other hand offers both; either the requested value, or a possible error. You can just continue using Result, which also has support for wrapping throws and much more, however keep in mind that this is not the direction Swift seems to intend to go 4. Otherwise, we'd have a full blown Result or Either type in Swift 2.

    I'm really happy about the introduction of try? as it will make many snippets, particularly when interacting with the Cocoa API, easier to solve.

    Footnotes:

    1

    Much like the lifting into / out of monads in Swift optionals is hidden via the ? syntax

    2

    There're ways to improve this code without try?, of course, but it makes for a nice example

    3

    Another is, of course, that I'm using raw NSRegularExpression here, instead of a simplifying library

    4

    Also, you'll always need to add additional dependencies to your project

    If you read this far, you should follow me (@terhechte)
    on Twitter


      Thu, 20 Aug 2015 #

      Match Me if you can: Swift Pattern Matching in Detail.

      This post is also available in 🇨🇳Chinese Thanks to SwiftGG
      This post is also available in 🇯🇵Japanese Thanks to M Ono

      Among the new features that Swift offers to Objective-C programmers is one that disguises itself like a boring old man while it offers huge potential for forming elegant solutions to otherwise unwieldy sets of nested branches. I'm, of course talking about the switch statement that many Objective-C programmers probably consider as a clunky syntax device which is most entertaining when used as Duff's Device, yet usually offers little to no advantages over multiple if statements.

      The Switch statement in Swift can do much more though. In the following tutorial, I will try to explain the various usages for these new features in more detail. I'll mostly ignore those solutions where there's no benefit over how switch works in Objective-C or C. The basics of this post were actually written in July 2014, but so many of my patterns crashed the compiler back then that I postponed writing it until there's better support.

      This Blog Post is also available in the following languages:

      1 Diving In

      The main feature of switch is of course pattern matching, the ability to destructure values and match different switch cases based on correct match of the values to the cases.

      // Example of the worst binary -> decimal converter in history
      let bool1 = 1
      let bool2 = 0
      switch (bool1, bool2) {
         case (0, 0): print("0")
         case (0, 1): print("1")
         case (1, 0): print("2")
         case (1, 1): print("3")
      }
      

      Pattern matching has long existed in other languages like Haskell, Erlang, Scala, or Prolog. This is a boon, because it allows us to have a look at how those languages utilize pattern matching in order to solve their problems. We can even have a look at their examples to find the most practical ones that offer real world adaptability.

      2 A Trading Engine

      So Wall Street contacted you, they need a new trading platform running on iOS devices. As it is a trading platform, you define an enum for trades.

      2.1 First Draft

      enum Trades {
          case Buy(stock: String, amount: Int, stockPrice: Float)
          case Sell(stock: String, amount: Int, stockPrice: Float)
      }
      

      You were also handed the following API to handle trades. Notice how sell orders are just negative amounts. And you're told the stock price is not important, their engine will take an internal one anyway.

      /**
       - parameter stock: The stock name
       - parameter amount: The amount, negative number = sell, positive = buy
      */
      func process(stock: String, _ amount: Int) {
          print ("\(amount) of \(stock)")
      }
      

      The next step is to process those trades. You see the potential for using pattern matching and write this:

      let aTrade = Trades.Buy(stock: "APPL", amount: 200, stockPrice: 115.5)
      
      switch aTrade {
      case .Buy(let stock, let amount, _):
          process(stock, amount)
      case .Sell(let stock, let amount, _):
          process(stock, amount * -1)
      }
      // Prints "buy 200 of APPL"
      

      Swift lets us conveniently only destructure / extract the information from the enum that we really want. In this case only the stock and the amount.

      Awesome, you visit Wall Street to show of your fantastic trading platform. However, as always, the reality is much more cumbersome than the beautiful theory. Trades aren't trades you learn.

      • You have to calculate in a fee which is different based on the trader type.
      • The smaller the institution the higher the fee.
      • Also, bigger institutions get a higher priority.

      They also realized that you'll need a new API for this, so you were handed this:

      func processSlow(stock: String, _ amount: Int, _ fee: Float) { print("slow") }
      func processFast(stock: String, _ amount: Int, _ fee: Float) { print("fast") }
      

      2.2 Trader Types

      So you go back to the drawing board and add another enum. The trader type is part of every trade, too.

      enum TraderType {
      case SingleGuy
      case Company
      } 
      
      enum Trades {
          case Buy(stock: String, amount: Int, stockPrice: Float, type: TraderType)
          case Sell(stock: String, amount: Int, stockPrice: Float, type: TraderType)
      }
      

      So, how do you best implement this new restriction? You could just have an if / else switch for buy and for sell, but that would lead to nested code which quickly lacks clarity - and who knows maybe these Wall Street guys come up with further complications. So you define it instead as additional requirements on the pattern matches:

      let aTrade = Trades.Sell(stock: "GOOG", amount: 100, stockPrice: 666.0, type: TraderType.Company)
      
      switch aTrade {
      case let .Buy(stock, amount, _, TraderType.SingleGuy):
          processSlow(stock, amount, 5.0)
      case let .Sell(stock, amount, _, TraderType.SingleGuy):
          processSlow(stock, -1 * amount, 5.0)
      case let .Buy(stock, amount, _, TraderType.Company):
          processFast(stock, amount, 2.0)
      case let .Sell(stock, amount, _, TraderType.Company):
          processFast(stock, -1 * amount, 2.0)
      }
      

      The beauty of this is that there's a very succinct flow describing the different possible combinations. Also, note how we changed .Buy(let stock, let amount) into let .Buy(stock, amount) in order to keep things simpler. This will destructure the enum just as before, only with less syntax.

      2.3 Guards! Guards!

      Once again you present your development to your Wall Street customer, and once again a new issue pops up (you really should have asked for a more detailed project description).

      • Sell orders exceeding a total value of $1.000.000 do always get fast handling, even if it's just a single guy.
      • Buy orders under a total value of $1.000 do always get slow handling.

      With traditional nested if syntax, this would already become a bit messy. Not so with switch. Swift includes guards for switch cases which allow you to further restrict the possible matching of those cases.

      You only need to modify your switch a little bit to accommodate for those new changes

      let aTrade = Trades.Buy(stock: "GOOG", amount: 1000, stockPrice: 666.0, type: TraderType.SingleGuy)
      
      switch aTrade {
      case let .Buy(stock, amount, _, TraderType.SingleGuy):
          processSlow(stock, amount, 5.0)
      case let .Sell(stock, amount, price, TraderType.SingleGuy)
          where price*Float(amount) > 1000000:
          processFast(stock, -1 * amount, 5.0)
      case let .Sell(stock, amount, _, TraderType.SingleGuy):
          processSlow(stock, -1 * amount, 5.0)
      case let .Buy(stock, amount, price, TraderType.Company)
          where price*Float(amount) < 1000:
          processSlow(stock, amount, 2.0)
      case let .Buy(stock, amount, _, TraderType.Company):
          processFast(stock, amount, 2.0)
      case let .Sell(stock, amount, _, TraderType.Company):
          processFast(stock, -1 * amount, 2.0)
      }
      

      This code is quite structured, still rather easy to read, and wraps up the complex cases quite well.

      That's it, we've successfully implemented our trading engine. However, this solution still has a bit of repetition; we wonder if there're pattern matching ways to improve upon that. So, let's look into pattern matching a bit more.

      3 Advanced Pattern Matching

      So now we've seen several patterns in action. But what's the syntax here? Which other things can we match for? Swift distinguishes 7 different patterns. We're going to have a quick look at each of them.

      All of those patterns can not only be used with the switch keyword, but also with the if, guard, and for keywords. For details on this, see below.

      3.1 1. Wildcard Pattern

      The wildcard pattern ignores the value to be matched against. In this case any value is possible. This is the same pattern as let _ = fn() where the _ indicates that you don't wish to further use this value. The interesting part is that this matches all values including nil 1. You can even match optionals by appending a ?:

      let p: String? = nil
      switch p {
      case _?: print ("Has String")
      case nil: print ("No String")
      }
      

      As you've seen in the trading example, it also allows you to omit the data you don't need from matching enums or tuples:

      switch (15, "example", 3.14) {
          case (_, _, let pi): print ("pi: \(pi)")
      }
      

      3.2 2. Identifier Pattern

      Matches a concrete value. This is how things work in Objective-C's switch implementation:

      switch 5 {
        case 5: print("5")
      }
      

      3.3 3. Value-Binding Pattern

      This is the very same as binding values to variables via let or var. Only in a switch statement. You've already seen this before, so I'll provide a very short example:

      switch (4, 5) {
        case let (x, y): print("\(x) \(y)")
      }
      

      3.4 4. Tuple Pattern

      I've written a whole blog post about tuples, which offer much more information than this, but here's a quick example:

      let age = 23
      let job: String? = "Operator"
      let payload: AnyObject = NSDictionary()
      
      switch (age, job, payload) {
        case (let age, _?, _ as NSDictionary):
        print(age)
        default: ()
      }
      

      Here, we're combining three values into a tuple (imagine they're coming from different API calls) and matching them in one go. Note that the pattern achieves three things:

      1. It extracts the age
      2. It makes sure there is a job, even though we don't need it
      3. It makes sure that the payload is of kind NSDictionary even though we don't need the actual value either.

      3.5 5. Enumeration Case Pattern

      As you saw in our trading example, pattern matching works really great with Swift's enums. That's because enum cases are like sealed, immutable, destructable structs. Much like with tuples, you can unwrap the contents of an individual case right in the match and only extract the information you need 2.

      Imagine you're writing a game in a functional style and you have a couple of entities that you need to define. You could use structs but as your entities will have very little state, you feel that that's a bit of an overkill.

      enum Entities {
          case Soldier(x: Int, y: Int)
          case Tank(x: Int, y: Int)
          case Player(x: Int, y: Int)
      }
      

      Now you need to implement the drawing loop. Here, we only need the X and Y position:

      for e in entities() {
          switch e {
          case let .Soldier(x, y):
            drawImage("soldier.png", x, y)
          case let .Tank(x, y):
            drawImage("tank.png", x, y)
          case let .Player(x, y):
            drawImage("player.png", x, y)
          }
      }
      

      3.6 6. Type-Casting Patterns

      As the name already implies, this pattern casts or matches types. It has two different keywords:

      • is type: Matches the runtime type (or a subclass of it) against the right hand side. This performs a type cast but disregards the returned type. So your case block won't know about the matched type.
      • pattern as type: Performs the same match as the is pattern but for a successful match casts the type into the pattern specified on the left hand side.

      Here is an example of the two.

      let a: Any = 5 
      switch a {
        // this fails because a is still anyobject
        // error: binary operator '+' cannot be applied to operands of type 'Any' and 'Int'
        case is Int: print (a + 1)
        // This works and returns '6'
        case let n as Int: print (n + 1)
        default: ()
      }
      

      Note that there is no pattern before the is. It matches directly against a.

      3.7 7. Expression Pattern

      The expression pattern is very powerful. It matches the switch value against an expression implementing the ~= operator. There're default implementations for this operator, for example for ranges, so that you can do:

      switch 5 {
       case 0..10: print("In range 0-10")
      }
      

      However, the much more interesting possibility is overloading the operator yourself in order to add matchability to your custom types. Let's say that you decided to rewrite the soldier game we wrote earlier and you want to use structs after all.

      struct Soldier {
        let hp: Int
        let x: Int
        let y: Int
      }
      

      Now you'd like to easily match against all entities with a health of 0. We can simply implement the ~= operators as follows.

      func ~= (pattern: Int, value: Soldier) -> Bool {
          return pattern == value.hp
      }
      

      Now we can match against an entity:

      let soldier = Soldier(hp: 99, x: 10, y: 10)
      switch soldier {
         case 0: print("dead soldier")
         default: ()
      }
      

      Sadly, full matching with tuples does not seem to work. If you implement the code below, there'll be a type checker error.

      func ~= (pattern: (hp: Int, x: Int, y: Int), value: Soldier) -> Bool {
         let (hp, x, y) = pattern
         return hp == value.hp && x == value.x && y == value.y
      }
      

      One possible way of implementing something akin to the above is by adding a unapply method to your struct and then matching against that:

      extension Soldier {
         func unapply() -> (Int, Int, Int) {
            return (self.hp, self.x, self.y)
         }
      }
      
      func ~= (p: (Int, Int, Int), t: (Int, Int, Int)) -> Bool {
         return p.0 == t.0 && p.1 == t.1 && p.2 == t.2 
      }
      
      let soldier = Soldier(hp: 99, x: 10, y: 10)
      print(soldier.unapply() ~= (99, 10, 10))
      

      But this is rather cumbersome and defeats the purpose of a lot of the magic behind pattern matching.

      In an earlier version of this post, I wrote that ~= doesn't work with protocols, but I was wrong. I remember that I tried it in a Playground, and it didn't work. However, this example (as kindly provided by latrodectus on reddit) does work fine:

      protocol Entity {
          var value: Int {get}
      }
      
      struct Tank: Entity {
          var value: Int
          init(_ value: Int) { self.value = value }
      }
      
      struct Peasant: Entity {
          var value: Int
          init(_ value: Int) { self.value = value }
      }
      
      func ~=(pattern: Entity, x: Entity) -> Bool {
          return pattern.value == x.value
      }
      
      switch Tank(42) {
          case Peasant(42): print("Matched") // Does match
          default: ()
      }
      

      There's a lot of things you can do with Expression Patterns. For a much more detailed explanation of Expression Patterns, have a look at this terrific blog post by Austin Zheng.

      This completes list of possible switch patterns. Before we move on, there's one final thing to discuss.

      3.8 Fallthrough, Break, and Labels

      The following is not directly related to pattern matching but only affects the switch keyword, so I'll keep it brief. By default, and unlike C/C++/Objective-C, switch cases do not fall through into the next case which is why in Swift, you don't need to write break for every case. You can opt into traditional fallthrough behaviour with the fallthrough keyword.

      switch 5 {
         case 5:
          print("Is 5")
          fallthrough
         default:
          print("Is a number")
      }
      // Will print: "Is 5" "Is a number"
      

      Alternatively, you can use break to break out of a switch statement early. Why would you do that if there's no default fallthrough? For example if you can only realize within the case that a certain requirement is not met and you can't execute the case any further:

      let userType = "system"
      let userID = 10
      switch (userType, userID)  {
         case ("system", _):
           guard let userData = getSystemUser(userID) else { break }
           print("user info: \(userData)")
           insertIntoRemoteDB(userData)
         default: ()
      }
      ... more code that needs to be executed
      

      Here, we don't want to call insertIntoRemoteData when the result from getSystemUser is nil. Of course, you could just use an if let here, but if multiple of those cases come together, you quickly end up with a bunch of horrifyingly ugly nested if lets.

      But what if you execute your switch in a while loop and you want to break out of the loop, not the switch? For those cases, Swift allows you to define labels to break or continue to:

      gameLoop: while true {
        switch state() {
           case .Waiting: continue gameLoop
           case .Done: calculateNextState()
           case .GameOver: break gameLoop
        }
      }
      

      We've discussed the syntax and implementation details of switch and pattern matching. Now, let us have a look at some interesting (more or less) real world examples.

      4 Real World Examples

      4.1 Optionals

      There're many ways to unwrap optionals, and pattern matching is one of them. You've probably used that quite frequently by now, nevertheless, here's a short example:

      var result: String? = secretMethod()
      switch result {
      case .None:
          println("is nothing")
      case let a:
          println("\(a) is a value")
      }
      

      With Swift 2.0, this becomes even easier:

      var result: String? = secretMethod()
      switch result {
      case nil:
          print("is nothing")
      case let a?:
          print("\(a) is a value")
      }
      

      As you can see, result could be a string, but it could also be nil. It's an optional. By switching on result, we can figure out whether it is .None or whether it is an actual value. Even more, if it is a value, we can also bind this value to variable right away. In this case a. What's beautiful here, is the clearly visible distinction between the two states, that the variable result can be in.

      4.2 Type Matches

      Given Swift's strong type system, there's usually no need for runtime type checks like it more often happens in Objective-C. However, when you interact with legacy Objective-C code (which hasn't been updated to reflect simple generics yet), then you often end up with code that needs to check for types. Imagine getting an array of NSStrings and NSNumbers:

      let u = NSArray(array: [NSString(string: "String1"), NSNumber(int: 20), NSNumber(int: 40)])
      

      When you go through this NSArray, you never know what kind of type you get. However, switch statements allow you to easily test for types here:

      for x in u {
          switch x {
          case _ as NSString:
      	print("string")
          case _ as NSNumber:
      	print("number")
          default:
      	print("Unknown types")
          }
      }
      

      4.3 Applying ranges for grading

      So you're writing the grading iOS app for your local Highschool. The teachers want to enter a number value from 0 to 100 and receive the grade character for it (A - F). Pattern Matching to the rescue:

      let aGrade = 84
      
      switch aGrade {
      case 90...100: print("A")
      case 80...90: print("B")
      case 70...80: print("C")
      case 60...70: print("D")
      case 0...60: print("F")
      default:
          print("Incorrect Grade")
      }
      

      4.4 Word Frequencies

      We have a sequence of pairs, each representing a word and its frequency in some text. Our goal is to filter out those pairs whose frequency is below or above a certain threshold, and then only return the remaining words, without their respective frequencies.

      Here're our words:

      let wordFreqs = [("k", 5), ("a", 7), ("b", 3)]
      

      A simple solution would be to model this with map and filter:

      let res = wordFreqs.filter({ (e) -> Bool in
          if e.1 > 3 {
      	return true
          } else {
      	return false
          }
      }).map { $0.0 }
      print(res)
      

      However, with flatmap a map that only returns the non-nil elements, we can improve a lot upon this solution. First and foremost, we can get rid of the e.1 and instead have proper destructuring by utilizing (you guessed it) tuples. And then, we only need one call flatmap instead of filter and then map which adds unnecessary performance overhead.

      let res = wordFreqs.flatMap { (e) -> String? in
          switch e {
          case let (s, t) where t > 3: return s
          default: return nil
          }
      }
      print(res)
      

      4.5 Directory Traversion

      Imagine you want to traverse a file hierachy and find:

      • all "psd" files from customer1 and customer2
      • all "blend" files from customer2
      • all "jpeg" files from all customers.
      guard let enumerator = NSFileManager.defaultManager().enumeratorAtPath("/customers/2014/")
      else { return }
      
      for url in enumerator {
          switch (url.pathComponents, url.pathExtension) {
      
          // psd files from customer1, customer2
          case (let f, "psd") 
      	    where f.contains("customer1") 
      	    || f.contains("customer2"): print(url)
      
          // blend files from customer2
          case (let f, "blend") where f.contains("customer2"): print(url)
      
          // all jpg files
          case (_, "jpg"): print(url)
      
          default: ()
          }
      }
      

      Note that contains stops at the first match and doesn't traverse the complete path. Again, pattern matching lead to very succinct and readable code.

      4.6 Fibonacci

      Also, see how beautiful an implementation of the fibonacci algorithm looks with pattern matching 3

      func fibonacci(i: Int) -> Int {
          switch(i) {
          case let n where n <= 0: return 0
          case 0, 1: return 1
          case let n: return fibonacci(n - 1) + fibonacci(n - 2)
          }
      }
      
      print(fibonacci(8))
      

      Of course, this will kill your stack with big numbers.

      4.7 Legacy API and Value Extractions

      Oftentimes, when you get data from an external source, like a library, or an API, it is not only good practice but usually even required that you check the data for consistency before interpreting it. You need to make sure that all keys exists or that the data is of the correct type, or the arrays have the required length. Not doing so can lead from buggy behaviour (missing key) to crash of the app (indexing non-existent array items). The classic way to do this is by nesting if statements.

      Let's imagine an API that returns a user. However, there're two types of users: System users - like the administrator, or the postmaster - and local users - like "John B", "Bill Gates", etc. Due to the way the system was designed and grew, there're a couple of nuisances that API consumers have to deal with:

      • system and local users come via the same API call.
      • the department key may not exist, since early versions of the db did not have that field and early employees never had to fill it out.
      • the name array contains either 4 items (username, middlename, lastname, firstname) or 2 items (full name, username) depending on when the user was created.
      • the age is an Integer with the age of the user

      Our system needs to create user accounts for all system users from this API with only the following information: username, department. We only need users born before 1980. If no department is given, "Corp" is assumed.

      func legacyAPI(id: Int) -> [String: AnyObject] {
          return ["type": "system", "department": "Dark Arts", "age": 57, 
      	   "name": ["voldemort", "Tom", "Marvolo", "Riddle"]] 
      }
      

      Given these constraints, let's develop a pattern match for it:

      let item = legacyAPI(4)
      switch (item["type"], item["department"], item["age"], item["name"]) {
         case let (sys as String, dep as String, age as Int, name as [String]) where 
            age < 1980 &&
            sys == "system":
           createSystemUser(name.count == 2 ? name.last! : name.first!, dep: dep ?? "Corp")
        default:()
      }
      
      // returns ("voldemort", "Dark Arts")
      

      Note that this code makes one dangerous assumption, which is that if the name array does not have 2 items, it must have 4 items. If that case doesn't hold, and we get a zero item name array, this would crash.

      Other than that, it is a nice example of how pattern matching even with just one case can help you write cleaner code and simplify value extractions.

      Also, see how we're writing let at the beginning right after the case, and don't have to repeat it for each assignment within the case.

      5 Patterns with other Keywords

      The Swift documentation points out, that not all patterns can be used with the if, for or the guard statement. However, the docs seem to be outdated. All 7 patterns work for all three keywords.

      For those interested, I compiled an example Gist that has an example for each pattern for each keyword.

      You can see the example patterns here.

      As a shorter example, see the Value Binding, Tuple, and Type Casting pattern used for all three keywords in one example:

      // This is just a collection of keywords that compiles. This code makes no sense
      func valueTupleType(a: (Int, Any)) -> Bool {
          // guard case Example
          guard case let (x, _ as String) = a else { return false}
          print(x)
      
          // for case example
          for case let (a, _ as String) in [a] {
      	print(a)
          }
      
          // if case example
          if case let (x, _ as String) = a {
             print("if", x)
          }
      
          // switch case example
          switch a {
          case let (a, _ as String):
      	print(a)
      	return true
          default: return false
          }
      }
      let u: Any = "a"
      let b: Any = 5
      print(valueTupleType((5, u)))
      print(valueTupleType((5, b)))
      // 5, 5, "if 5", 5, true, false
      

      With this in mind, we will have a short look at each of those keywords in detail.

      6 Using for case

      With Swift 2.0, pattern matching has become even more important in the language as the switch capabilities have been extended to other keywords as well. For example, let's write a simple array function which only returns the non-nil elements

      func nonnil<T>(array: [T?]) -> [T] {
         var result: [T] = []
         for case let x? in array {
            result.append(x)
         }
         return result
      }
      
      print(nonnil(["a", nil, "b", "c", nil]))
      

      The case keyword can be used in for loops just like in switch cases. Here's another example. Remember the game we talked about earlier? Well, after the first refactoring, our entity system now looks like this:

      enum Entity {
          enum EntityType {
      	case Soldier
      	case Player
          }
          case Entry(type: EntityType, x: Int, y: Int, hp: Int)
      }
      

      Fancy, this allows us to draw all items with even less code:

      for case let Entity.Entry(t, x, y, _) in gameEntities()
      where x > 0 && y > 0 {
          drawEntity(t, x, y)
      }
      

      Our one line unwraps all the necessary properties, makes sure we're not drawing beyond 0, and finally calls the render call (drawEntity).

      In order to see if the player won the game, we want to know if there is at least one Soldier with health > 0

      func gameOver() -> Bool {
          for case Entity.Entry(.Soldier, _, _, let hp) in gameEntities() 
          where hp > 0 {return false}
          return true
      }
      print(gameOver())
      

      What's nice is that the Soldier match is part of the for query. This feels a bit like SQL and less like imperative loop programming. Also, this makes our intent clearer to the compiler, opening up the possibilities for dispatch enhancements down the road. Another nice touch is that we don't have to spell out Entity.EntityType.Soldier. Swift understands our intent even if we only write .Soldier as above.

      7 Using guard case

      Another keyword which supports patterns is the newly introduced guard keyword. You know how it allows you to bind optionals into the local scope much like if let only without nesting things:

      func example(a: String?) {
          guard let a = a else { return }
          print(a)
      }
      example("yes")
      

      guard let case allows you to do something similar with the power that pattern matching introduces. Let's have a look at our soldiers again. We want to calculate the required HP until our player has full health again. Soldiers can't regain HP, so we should always return 0 for a soldier entity.

      let MAX_HP = 100
      
      func healthHP(entity: Entity) -> Int {
          guard case let Entity.Entry(.Player, _, _, hp) = entity 
          where hp < MAX_HP 
          else { return 0 }
          return MAX_HP - hp
      }
      
      print("Soldier", healthHP(Entity.Entry(type: .Soldier, x: 10, y: 10, hp: 79)))
      print("Player", healthHP(Entity.Entry(type: .Player, x: 10, y: 10, hp: 57)))
      
      // Prints:
      "Soldier 0"
      "Player 43"
      

      This is a beautiful example of the culmination of the various mechanisms we've discussed so far.

      • It is very clear, there is no nesting involved
      • Logic and initialization of state are handled at the top of the func which improves readability
      • Very terse.

      This can also be very successfully combined with switch and for to wrap complex logical constructs into an easy to read format. Of course, that won't make the logic any easier to understand, but at least it will be provided in a much saner package. Especially if you use enums.

      8 Using if case

      if case can be used as the opposite of guard case. It is a great way to unwrap and match data within a branch. In line with our previous guard example. Obviously, we need an move function. Something that allows us to say that an entity moved in a direction. Since our entities are enums, we need to return an updated entity.

      func move(entity: Entity, xd: Int, yd: Int) -> Entity {
      	if case Entity.Entry(let t, let x, let y, let hp) = entity
      	where (x + xd) < 1000 &&
      	    (y + yd) < 1000 {
      	return Entity.Entry(type: t, x: (x + xd), y: (y + yd), hp: hp)
          }
          return entity
      }
      print(move(Entity.Entry(type: .Soldier, x: 10, y: 10, hp: 79), xd: 30, yd: 500))
      // prints: Entry(main.Entity.EntityType.Soldier, 40, 510, 79)
      

      9 Limitations

      Some limitations were already mentioned in the text, such as the issues regarding Expression Patterns, which seem to not match against tuples (as would be really convenient). In Scala or Clojure, pattern matching can also work against collections, so you could match head, tail, parts, etc. 4 This doesn't work in Swift (although Austin Zheng kinda implemented this in the blog post I linked above).

      Another thing which doesn't work (wich, again, Scala does just fine) is destructuring against classes or structs. Scala allows us to define an unapply method which does basically the opposite of init. Implementing this method, then, allows the type checker to match against classes. In Swift, this could look as follows:

      struct Imaginary {
         let x: Int
         let y: Int
         func unapply() -> (Int, Int) {
           // implementing this method would then in theory provide all the details needed to destructure the vars
           return (self.x, self.y)
         }
      }
      // this, then, would unapply automatically and then match
      guard case let Imaginary(x, y) = anImaginaryObject else { break }
      

      10 Changes

      08/21/2015 Incorporated helpful feedback from foBrowsing on Reddit

      • Added guard case let
      • Added simplified syntax for let (i.e. let (x, y) instead of (let x, let y)

      08/22/2015 Apparently I didn't test some things properly enough. Some of the limitations I listed do actually work, as another helpful Reddit commenter (latrodectus) pointed out.

      • All patterns work for all three keywords. Changed that, and added a Gist with examples
      • The limitations regarding protocols and the expression pattern were invalid. This works fine, too.
      • Added "Pattern Availability" section

      08/24/2015

      • Added if case examples, renamed some sections.
      • Fixed typos in the text. In particular, I accidentally wrote that _ does not match nil. That's of course not true, _ matches everything. (thanks to obecker)

      09/18/2015

      • Added link to Japanese Translation

      Footnotes:

      1

      Think of it like the * wildcard you use in the shell

      2

      I'm not sure whether the compiler optimizes for this, but theoretically, it should be able to calculate the correct position of the requested data and inline the address ignoring the other parts of the enum case

      3

      of course, no match for a Haskell implementation:
      fib 0 = 0
      fib 1 = 1
      fib n = fib (n-1) + fib (n-2)

      4

      I.e. switch [1, 2, 4, 3] {
      case [_, 2, _, 3]:
      }

      If you read this far, you should follow me (@terhechte)
      on Twitter


        Sun, 19 Jul 2015 #

        Tuples in Swift, Advanced Usage and Best Practices

        An older version of this post is also available in 🇨🇳Chinese Thanks to SwiftGG

        Tuples are one of Swift's less visible language features. They occupy a small space between Structs and Arrays. In addition, there's no comparable construct in Objective-C (or many other languages). Finally, the usage of tuples in the standard library and in Apple's example code is sparse. One could get the impression that their raison d'être in Swift is pattern matching, but I disgress.

        Most tuple explanations concentrate on three tuple use cases (pattern matching, return values, destructuring) and leave it at that. The following guide tries to give a more comprehensive overview of tuples with best practices of when to use them and when not to use them. I'll also try to list those things that you can't do with tuples, to spare you asking about them on stack overflow. Let's dive in.

        1 The absolute basics

        You probably already know most of this, so I'll keep it concise.

        A tuple can combine different types into one. Tuples are value types and even though they look like sequences they aren't sequences, as there's no direct way of looping over the contents. We'll start with a quick primer on how to create and use tuples.

        1.1 Creating and Accessing Tuples

        // Constructing a simple tuple
        let tp1 = (2, 3)
        let tp2 = (2, 3, 4)
        
        // Constructing a named tuple
        let tp3 = (x: 5, y: 3)
        
        // Different types
        let tp4 = (name: "Carl", age: 78, pets: ["Bonny", "Houdon", "Miki"])
        
        // Accessing tuple elements
        let tp5 = (13, 21)
        tp5.0 // 13
        tp5.1 // 21
        
        let tp6 = (x: 21, y: 33)
        tp6.x // 21
        tp6.y // 33
        

        1.2 Tuples for pattern matching

        As already mentioned above, this feels like the strongest use case for tuples. Swift's switch statement offers a really powerful yet easy way to define complex conditionals without cluttering up the source code. You can then match for the type, existence, and value of multiple variables in one statement:

        // Contrived example
        // These would be return values from various functions.
        let age = 23
        let job: String? = "Operator"
        let payload: Any = ["cars": 1]
        

        In the code above, we want to find the persons younger than 30 with a job and a Dictionary payload. Imagine the payload as something from the Objective-C world, it could be a Dictionary or an Array or a Number, awful code somebody else wrote years ago, and you have to interact with it now.

        typealias AnyDictionary = Dictionary<AnyHashable, Any>
        
        switch (age, job, payload) {
        case (let age, _?, _ as AnyDictionary) where age < 30:
            print(age)
        default:
            break
        }
        

        By constructing the switch argument as a tuple (age, job, payload) we can query for specific or nonspecific attributes of all tuple elements at once. This allows for elaborately constrained conditionals.

        1.3 Tuples as return types

        Probably the next-best tuple use case. Since tuples can be constructed on the fly, they're a great way to easily return multiple values from a function.

        func abc() -> (Int, Int, String) {
            return (3, 5, "Carl")
        }
        

        1.4 Tuple Destructuring

        Swift took a lot of inspiration from different programming languages, and this is something that Python has been doing for years. While the previous examples mostly showed how to easily get something into a tuple, destructuring is a swifty way of getting something out of a tuple, and in line with the abc example above, it looks like this:

        let (a, b, c) = abc()
        print(a)
        

        Another example is getting several function calls into one line:

        let (a, b, c) = (a(), b(), c())
        

        Or, an easy way to swap two values:

        var v1: Int
        var v2: Int
        (v1, v2) = (5, 4)
        (a: v1, b: v2) = (a: v2, b: v1) // swapped: v1 == 4, v2 == 5
        (v1, v2) = (5, 4)
        (a: v1, b: v2) = (b: v1, a: v2) // swapped: v1 == 4, v2 == 5
        

        2 Beyond the basics

        2.1 Tuples as anonymous structs

        Tuples as well as structs allow you to combine different types into one type:

        let user1 = (name: "Carl", age: 40)
        // vs.
        struct User {
            let name: String
            let age: Int
        }
        let user2 = User(name: "Steve", age: 39)
        

        As you can see, these two types are similar, but whereas the tuple exists simply as an instance, the struct requires both a struct declaration and a struct initializer. This similarity can be leveraged whenever you have the need to define a temporary struct inside a function or method. As the Swift docs say:

        Tuples are useful for temporary groups of related values. (…) If your data structure is likely to persist beyond a temporary scope, model it as a class or structure (…)

        As an example of this, consider the following situation where the return values from several functions first need to be uniquely collected and then inserted:

        func zipForUser(userid: String) -> String { return "12124" }
        func streetForUser(userid: String) -> String { return "Charles Street" }
        let users = [user1]
        
        // Find all unique streets in our userbase
        var streets: [String: (zip: String, street: String, count: Int)] = [:]
        for user in users {
            let zip = zipForUser(userid: user.name)
            let street = streetForUser(userid: user.name)
            let key = "\(zip)-\(street)"
            if let (_, _, count) = streets[key] {
        	streets[key] = (zip, street, count + 1)
            } else {
        	streets[key] = (zip, street, 1)
            }
        }
        
        // drawStreetsOnMap(streets.values)
        for street in streets.values { print(street) }
        

        Here, the tuple is being used as a simple structure for a short-duration use case. Defining a struct would also be possible but not strictly necessary.

        Another example would be a class that handles algorithmic data, and you're moving a temporary result from one method to the next one. Defining an extra struct for something only used once (in between two or three methods) may not be required.

        // Made up algorithm
        func calculateInterim(values: [Int]) -> (r: Int, alpha: CGFloat, chi: (CGFloat, CGFloat)) {
            return (values[0], 2, (4, 8))
        }
        func expandInterim(interim: (r: Int, alpha: CGFloat, chi: (CGFloat, CGFloat))) -> CGFloat {
            return CGFloat(interim.r) + interim.alpha + interim.chi.0 + interim.chi.1
        }
        
        print(expandInterim(interim: calculateInterim(values: [1])))
        

        There is, of course, a fine line here. Defining a struct for one instance is overly complex; defining a tuple 4 times instead of one struct is overly complex too. Finding the sweet spot depends on various factors.

        2.2 Private State

        In addition to the previous example, there are also use cases where using tuples beyond a temporary scope is useful. Following Rich Hickey's "If a tree falls in the woods, does it make a sound?", as long as the scope is private and the tuple's type isn't littered all over the implementation, using tuples to store internal state can be fine.

        A simple and contrived example would be storing a static UITableView structure that displays various information from a user profile and contains the key path to the actual value as well as a flag noting whether the value can be edited when tapping on the cell.

        let tableViewValues = [
            (title: "Age", value: "user.age", editable: true),
            ("Name",           "user.name.combinedName",  true),
            ("Username",       "user.name.username",      false),
            ("ProfilePicture", "user.pictures.thumbnail", false)]
        

        The alternative would be to define a struct, but if the data is a purely private implementation detail, a tuple works just as well.

        A better example is when you define an object and want to add the ability to add multiple change listeners to your object. Each listener consists of a name and the closure to be called upon any change:

        typealias Action = (_ change: Any?) -> Void
        func addListener(name: String, action: @escaping Action) { }
        func removeListener(name: String) { }
        

        How will you store these listeners in your object? The obvious solution would be to define a struct, but this is a very limited scope, and the struct will only be internal, and it will be used in only three cases. Here, using a tuple may even be the better solution, as the destructuring makes things simpler:

        class ListenerStuff {
        
            typealias Action = (_ change: Any?) -> Void
        
            var listeners: [(String, Action)] = []
        
            func addListener(name: String, action: @escaping Action) {
        	listeners.append((name, action))
            }
        
            func removeListener(name: String) {
        	if let idx = listeners.index(where: { $0.0 == name }) {
        	    listeners.remove(at: idx)
        	}
            }
        
            func execute(change: Int) {
        	for (_, listener) in listeners {
        	    listener(change as Any?)
        	}
            }
        }
        
        var stuff = ListenerStuff()
        let ourAction: ListenerStuff.Action = { x in print("Change is \(x ?? "NONE").") }
        stuff.addListener(name: "xx", action: ourAction)
        stuff.execute(change: 17)
        

        As you can see in the execute function, the destructuring abilities make tuples especially useful in this case, as the contents are directly destructured into the local scope.

        2.3 Tuples as Fixed-Size Sequences

        Another area where tuples can be used is when you intend to constrain a type to a fixed number of items. Imagine an object that calculates various statistics for each month in a year. You need to store a certain Integer value for each month separately. The solution that comes to mind first would of course be:

        var monthValuesArray: [Int]
        

        However, in this case we don't know whether the property indeed contains 12 elements. A user of our object could accidentally insert 13 values, or 11. We can't tell the type checker that this is a fixed size array of 12 items1. With a tuple, this specific constraint can easily be put into place:

        var monthValues: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)
        

        The alternative would be to have the constraining logic in the object's functionality (say via a guard statement); however, this would be a run time check. The tuple check happens at compile time; your code won't even compile if you try to give 11 months to your object.

        2.4 Tuples for Varargs Types

        Varargs i.e. variable function arguments are a very useful technique for situations where the number of function parameters is unknown.

        // classic example
        func sum(of numbers: Int...) -> Int {
            // add up all numbers with the + operator
            return numbers.reduce(0, +)
        }
        
        let theSum = sum(of: 1, 2, 5, 7, 9) // 24
        

        A tuple can be useful here if your requirement goes beyond simple integers. Take this function, which does a batch update of n entities in a database:

        func batchUpdate(updates: (String, Int)...) {
            self.db.begin()
            for (key, value) in updates {
        	self.db.set(key, value)
            }
            self.db.end()
        }
        
        // We're imagining a weird database
        batchUpdate(updates: ("tk1", 5), ("tk7", 9), ("tk21", 44), ("tk88", 12))
        

        3 Advanced Tuples

        3.1 Tuple Iteration

        In the above descriptions, I've tried to steer clear of calling tuples sequences or collections because they aren't. Since every element of a tuple can have a different type, there's no type-safe way of looping or mapping over the contents of a tuple. Well, no beautiful one, that is.

        Swift does offer limited reflection capabilities, and these allow us to inspect the elements of a tuple and loop over them. The downside is that the type checker has no way to figure out what the type of each element is, and thus everything is typed as Any. It is your job then to cast and match this against your possible types to figure out what to do.

        let t = (a: 5, b: "String", c: Date())
        
        let mirror = Mirror(reflecting: t)
        for (label, value) in mirror.children {
            switch value {
            case is Int:
        	print("int")
            case is String:
        	print("string")
            case is NSDate:
        	print("nsdate")
            default: ()
            }
        }
        

        This is not as simple as array iteration, but it does work if you really need it.

        3.2 Tuples and Generics

        There's no Tuple type available in Swift. If you wonder why that is, think about it: every tuple is a totally different type, depending on the types within it. So instead of defining a generic tuple requirement, you define the specific but generic incarnation of the tuple you intend to use:

        func wantsTuple<T1, T2>(_ tuple: (T1, T2)) -> T1 {
            return tuple.0
        }
        
        wantsTuple(("a", "b")) // "a"
        wantsTuple((1, 2)) // 1
        

        You can also use tuples in typealiases, thus allowing subclasses to fill out your types with details. This looks fairly useless and complicated, but I've already had a use case where I need to do exactly this.

        class BaseClass<A,B> {
            typealias Element = (A, B)
            func add(_ elm: Element) {
        	print(elm)
            }
        }
        class IntegerClass<B> : BaseClass<Int, B> {
        }
        let example = IntegerClass<String>()
        example.add((5, ""))
        // Prints (5, "")
        

        3.3 Define a Specific Tuple Type

        In many of the earlier examples, we rewrote a certain tuple type like (Int, Int, String) multiple times. This, of course, is not necessary, as we could define a typealias for it:

        typealias Example = (Int, Int, String)
        func add(elm: Example) { }
        

        However, if you're using a certain tuple construction so often that you think about adding a typealias for it, you might really be better off defining a struct.

        3.4 Tuples as function parameters

        Swift 3 removed the tuple splat feature, which used to be described in this section.

        If you pass a tuple as a parameter to a function, it always works as you would expect: the tuple is available as an immutable variable in the function.

        3.5 Tuples to reorder function parameters

        Swift 3 removed the tuple splat feature, which was the basis for tricks discussed in this section.

        4 Tuple impossibilities

        Finally, we reach the list of some of the things that are impossible to achieve with tuples.

        4.1 Tuples as Dictionary Keys

        If you'd like to do the following:

        let p: [(Int, Int): String]
        

        Then this is not possible, because tuples don't conform to the Hashable protocol. Which is really a bummer, as the example above has a multitude of use cases. There may be a crazy type checker hack to extend tuples of varying arities to the Hashable protocol, but I haven't really looked into that. If you happen to know if this works, feel free to contact me via twitter.

        4.2 Tuple Protocol Compliance

        Given the following protocol:

        protocol PointProtocol {
            var x: Int { get }
            var y: Int { get }
        }
        

        You can't get the type checker to accept the tuple (x: 10, y: 20) as implementing that protocol.

        func addPoint(point: PointProtocol)
        addPoint(point: (x: 10, y: 20) as PointProtocol) // doesn't work.
        

        The compiler complains, "'(x: Int, y: Int)' is not convertible to 'PointProtocol'; did you mean to use 'as!' to force downcast? (Answer: no.)

        5 Addendum

        That's it. I probably forgot one or another thing. Things may also be wrong. If you find a factual error, or if there's something else I forgot, feel free to contact me.

        6 The code, suitable for use in a playground

        import AppKit
        
        // * Creating and Accessing Tuples
        
        // Constructing a simple tuple
        let tp1 = (2, 3)
        let tp2 = (2, 3, 4)
        
        // Constructing a named tuple
        let tp3 = (x: 5, y: 3)
        
        // Different types
        let tp4 = (name: "Carl", age: 78, pets: ["Bonny", "Houdon", "Miki"])
        
        // Accessing tuple elements
        let tp5 = (13, 21)
        tp5.0 // 13
        tp5.1 // 21
        
        let tp6 = (x: 21, y: 33)
        tp6.x // 21
        tp6.y // 33
        
        
        // * Tuples for pattern matching
        
        // Contrived example
        // These would be return values from various functions.
        let age = 23
        let job: String? = "Operator"
        let payload: Any = ["cars": 1]
        
        typealias AnyDictionary = Dictionary<AnyHashable, Any>
        
        switch (age, job, payload) {
        case (let age, _?, _ as AnyDictionary) where age < 30:
            print(age)
        default: ()
        }
        
        
        // * Tuples as return types
        
        func abc() -> (Int, Int, String) {
            return (3, 5, "Carl")
        }
        
        
        // * Tuple Destructuring
        
        let (a, b, c) = abc()
        print(a)
        
        func f1() -> Int { return 1 }
        func f2() -> Int { return 2 }
        func f3() -> Int { return 3 }
        
        let (r1, r2, r3) = (f1(), f2(), f3())
        
        var v1: Int
        var v2: Int
        (v1, v2) = (5, 4)
        (a: v1, b: v2) = (a: v2, b: v1) // swapped: v1 == 4, v2 == 5
        (v1, v2) = (5, 4)
        (a: v1, b: v2) = (b: v1, a: v2) // swapped: v1 == 4, v2 == 5
        
        
        // * Tuples as anonymous structs
        
        let user1 = (name: "Carl", age: 40)
        // vs.
        struct User {
            let name: String
            let age: Int
        }
        let user2 = User(name: "Steve", age: 39)
        
        func zipForUser(userid: String) -> String { return "12124" }
        func streetForUser(userid: String) -> String { return "Charles Street" }
        let users = [user1]
        
        // Find all unique streets in our userbase
        var streets: [String: (zip: String, street: String, count: Int)] = [:]
        for user in users {
            let zip = zipForUser(userid: user.name)
            let street = streetForUser(userid: user.name)
            let key = "\(zip)-\(street)"
            if let (_, _, count) = streets[key] {
        	streets[key] = (zip, street, count + 1)
            } else {
        	streets[key] = (zip, street, 1)
            }
        }
        
        // drawStreetsOnMap(streets.values)
        for street in streets.values {
            print(street)
        }
        
        
        // Made up algorithm
        func calculateInterim(values: [Int]) -> (r: Int, alpha: CGFloat, chi: (CGFloat, CGFloat)) {
            return (values[0], 2, (4, 8))
        }
        func expandInterim(interim: (r: Int, alpha: CGFloat, chi: (CGFloat, CGFloat))) -> CGFloat {
            return CGFloat(interim.r) + interim.alpha + interim.chi.0 + interim.chi.1
        }
        
        print(expandInterim(interim: calculateInterim(values: [1])))
        
        
        // * Private State
        
        let tableViewValues = [
            (title: "Age", value: "user.age", editable: true),
            ("Name",           "user.name.combinedName",  true),
            ("Username",       "user.name.username",      false),
            ("ProfilePicture", "user.pictures.thumbnail", false)]
        
        
        class ListenerStuff {
        
            typealias Action = (_ change: Any?) -> Void
        
            var listeners: [(String, Action)] = []
        
            func addListener(name: String, action: @escaping Action) {
        	listeners.append((name, action))
            }
        
            func removeListener(name: String) {
        	if let idx = listeners.index(where: { $0.0 == name }) {
        	    listeners.remove(at: idx)
        	}
            }
        
            func execute(change: Int) {
        	for (_, listener) in listeners {
        	    listener(change as Any?)
        	}
            }
        }
        
        var stuff = ListenerStuff()
        let ourAction: ListenerStuff.Action = { x in print("Change is \(x ?? "NONE").") }
        stuff.addListener(name: "xx", action: ourAction)
        stuff.execute(change: 17)
        
        
        // * Tuples as Fixed-Size Sequences
        
        var monthValuesArray: [Int]
        
        
        var monthValues: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int)
        
        
        // * Tuples for Varargs Types
        
        // classic example
        func sum(of numbers: Int...) -> Int {
            // add up all numbers with the + operator
            return numbers.reduce(0, +)
        }
        
        let theSum = sum(of: 1, 2, 5, 7, 9) // 24
        print(theSum)
        
        func batchUpdate(updates: (String, Int)...) {
            //self.db.begin()
            for (key, value) in updates {
        	print("self.db.set(\"\(key)\", \(value))")
        	//self.db.set(key, value)
            }
            //self.db.end()
        }
        
        // We're imagining a weird database
        batchUpdate(updates: ("tk1", 5), ("tk7", 9), ("tk21", 44), ("tk88", 12))
        
        
        // * Advanced Tuples
        
        // ** Tuple Iteration
        
        let t = (a: 5, b: "String", c: Date())
        
        let mirror = Mirror(reflecting: t)
        for (label, value) in mirror.children {
            switch value {
            case is Int:
        	print("int")
            case is String:
        	print("string")
            case is NSDate:
        	print("nsdate")
            default: ()
            }
        }
        
        // ** Tuples and Generics
        
        func wantsTuple<T1, T2>(_ tuple: (T1, T2)) -> T1 {
            return tuple.0
        }
        
        let tr1 = wantsTuple(("a", "b")) // "a"
        let tr2 = wantsTuple((1, 2)) // 1
        
        
        class BaseClass<A,B> {
            typealias Element = (A, B)
            func add(_ elm: Element) {
        	print(elm)
            }
        }
        class IntegerClass<B> : BaseClass<Int, B> {
        }
        let example = IntegerClass<String>()
        example.add((5, ""))
        // Prints (5, "")
        
        
        // ** Define a Specific Tuple Type
        
        typealias Example = (Int, Int, String)
        func add(elm: Example) { }
        
        
        // ** Tuples as Dictionary Keys
        
        
        // let p: [(Int, Int): String]  // doesn't compile
        
        
        // ** Tuple Protocol Compliance
        
        protocol PointProtocol {
            var x: Int { get }
            var y: Int { get }
        }
        
        func addPoint(point: PointProtocol) {
            print(point)
        }
        
        // addPoint(point: (x: 10, y: 20) as PointProtocol) // doesn't work.
        // The compiler complains,
        //    "'(x: Int, y: Int)' is not convertible to 'PointProtocol'; did you mean to use 'as!' to force downcast?
        

        7 Changes

        07/23/2015 Added section on tuples as function parameters

        08/06/2015 Updated the Reflection example to the latest Swift beta 4. (It removes the reflect call)

        08/12/2015 Updated the Tuples as function parameters with a couple more examples and more information.

        08/13/2015 Fixed a couple of bugs..

        10/28/2015 Fixed bugs and added a new section on parameter reordering.

        Footnotes:

        1

        Interestingly, something that C can do just fine

        If you read this far, you should follow me (@terhechte)
        on Twitter


          Thu, 2 Jul 2015 #

          Debugging advanced compilation errors in ClojureScript

          Just a quick note so I can easily look this up again and maybe help others in a similar situation. When you're working on a ClojureScript app and there're errors in advanced compilation mode which do not appear in the dev environment, tracking down these bugs can be quite daunting.

          Thankfully, there's a compiler setting which tries to emit readable names during compilation: :pseudo-names true. The documentation says:

          With :advanced mode optimizations, determines whether readable names are emitted. This can be useful when debugging issues in the optimized JavaScript and can aid in finding missing externs. Defaults to false.

          Together with :pretty-print true this helps a lot in finding out just where the bug you're seeing originated.

          An Example:

          {
              :optimizations :advanced
              :pretty-print true
              :pseudo-names true
          }
          

          If you read this far, you should follow me (@terhechte)
          on Twitter