Slides for a talk on the Swift programming language's support for enumerated types, pattern matching (via the 'switch' statement), and generic programming.
StringNode(String) case NumberNode(Float) case BoolNode(Bool) case ArrayNode([JSONNode]) case ObjectNode([String:JSONNode]) } ! let x : JSONNode = .ArrayNode( [.NumberNode(10.0), .StringNode("hello"), .BoolNode(false)])
"France": println("!") case "Germany": println(""") case "Italy": println("#") case "Russia": println("$") case "Spain": println("%") case "United Kingdom": println("&") default: println("Other") } (actually, any Equatable type)
("Helen", let age): println("Your name is Helen, and you are \(age)" + " years old") case (_, 13...19): println("You are a teenager") case ("Bob", _): println("You are not a teenager, but your name" + " is Bob.") case (_, _): println("no comment") }
{ case let (x, y): "The string in 'x' is \(x); " + "the integer in 'y' is \(y)" case (let x, let y): "Another way to do the exact same thing" case (_, let y): "We don't care about the string in 'x', " + "but the integer in 'y' is \(y)" }
let a = ParseResult.NumericValue(1) switch a { case let .NumericValue(v): "Success; numeric value is \(v)" case .Error(let err): "Failed; error message is \(err)" }
myView { case is UIImageView: println("It's an image view") case let lbl as UILabel: println("It's a label, with text \(lbl.text)") case let tv as UITableView: println("It's a table view, with" + " \(tv.numberOfSections()) sections") default: println("It's some other type of view") }
{ case _ where myView.frame.size.height < 50: println("Your view is shorter than 50 units") case _ where myView.frame.size.width > 20: println("Your view is at least 50 units tall," + " and is more than 20 units wide") case _ where myView.backgroundColor == UIColor.greenColor(): println("Your view is at least 50 units tall," + " at most 20 units wide, and is green.") default: println("I can't describe your view.") }
switch myArray { case [.FromBeginning, .Literal(0), .Literal(0), .Literal(0)]: "last three elements are 0" case [.Literal(4), .ToEnd]: "first element is 4, everything else doesn't matter" case [.Wildcard, .Literal(2), .Wildcard, .Literal(4)]: "4 elements; second element is 2, fourth element is 4" case [.Wildcard, .Wildcard, .Literal(3), .Wildcard]: "third element (out of 4) is 3" case [.Wildcard, .Wildcard, .Wildcard, .Literal(3)]: "fourth element (out of 4) is 3" default: "catchall" }
0] switch anotherArray { case [<~nil, *0, *0, *0]: "last three elements are 0" case [*4, nil~>]: "first element is 4" case [nil, *2, nil, *2]: "4 elements; 2nd is 2, 4th is 4" case [nil, nil, *3, nil]: "third element (out of 4) is 3" case [nil, nil, nil, *3]: "fourth element (out of 4) is 3" default: "catchall" }
one, or multiple protocols • Protocols can ‘inherit’ from other protocols - they implicitly get their parent’s methods/properties • Protocols are not traits - can’t specify implementation
• Type information is available at runtime • Compiler can optimize by creating specific versions for common cases (C++ templates), and fall back to the generic implementation
{ var x: T? = nil func instantiate() -> T { return T() } } ! struct AnotherStruct: InitProtocol { func favoriteString() -> String { return "reify me please" } } ! let c = SomeStruct<AnotherStruct>() let d = c.instantiate() d.favoriteString() ‘?’ just means this is allowed to be nil
a collection, take an array, and append the items in that collection to the array • We want this function to be typesafe • We want to write one function that handles every case • Array, Dictionary, SquareMatrix, TreeNode
leftNode : TreeNode? let rightNode : TreeNode? init(value: T, left: TreeNode?, right: TreeNode?) { self.value = value self.leftNode = left self.rightNode = right } } An aside: would have preferred to use enums.
U == T.ElementType> (source: T, inout dest: Array<U>) { ! let a = source.allElements() for element in a { dest.append(element) } } ! var buffer = ["a", "b", "c"] appendToArray([1: "foo", 2: "bar"], &buffer)
• See: Generator, EnumerateGenerator, etc • http://www.scottlogic.com/blog/2014/06/26/swift-sequences.html • Still have to implement Sequence for custom types…but you get all Sequence functionality
a protocol (e.g. T.SomeType : MyProtocol) • Specify that a class inherits from another class (e.g. T : SomeParentClass) • Specify equality of types (e.g. T.ContainerType == U.ContainerType)