pooya khaloo presentation on iwmc 2015
TRANSCRIPT
let individualScores = [75, 43, 103, 87, 12] var teamScore = 0 for score in individualScores { if score > 50 { teamScore += 3 } else { teamScore += 1 } } teamScore
var optionalName: String? = "John Appleseed" var greeting = "Hello!" !if optionalName { greeting = "Hello, \(optionalName!)" }
Optional
var optionalName: String? = "John Appleseed" var greeting = "Hello!" !if let name = optionalName { greeting = "Hello, \(name)" }
Optional
if let upper = john.residence?.address?.buildingIdentifier()?.uppercaseString { println("John's uppercase building identifier is \(upper).") } else { println("I can't find John's address") }
Optional Chaining
let vegetable = "red pepper" switch vegetable { case "celery": let vegetableComment = "Add raisins." case "cucumber", "watercress": let vegetableComment = "sandwich." case let x where x.hasSuffix("pepper"): let vegetableComment = "Is it a spicy \(x)?" default: let vegetableComment = "Soup." }
let somePoint = (1, 1) switch somePoint { case (0, 0): println("(0, 0) is at the origin") case (_, 0): println("(\(somePoint.0), 0) is on the x-axis") case (0, _): println("(0, \(somePoint.1)) is on the y-axis") case (-2...2, -2...2): println("(\(somePoint.0), \(somePoint.1)) is inside the box") default: println("(\(somePoint.0), \(somePoint.1)) is outside of the box") }
func greet(name: String, #day: String) -> String { return "Hello \(name), today is \(day)." } greet("Bob", day: "Wednesday")
Named Parameters
func greet(name: String, day: String) -> String { return "Hello \(name), today is \(day)." } greet("Bob", "Wednesday")
Named Parameters Optional
Multiple result using tuples
func getGasPrices()->(Double, Double, Double) { return (3.59, 3.69, 3.79) } let (min, avg, max) = getGasPrices() println("min is \(min), max is \(max)")
Multiple result using tuples
func getGasPrices()->(Double, Double, Double) { return (3.59, 3.69, 3.79) } let gasPrices = getGasPrices() println("min is \(gasPrices.0), max is \(gasPrices.2)")
func makeIncrementer() -> (Int -> Int) { func addOne(number: Int) -> Int { return 1 + number } return addOne } var increment = makeIncrementer() increment(7)
A function can be a return value
or a function parameter
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool { for item in list { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } var numbers = [20, 19, 7, 12] hasAnyMatches(numbers, lessThanTen)
anonymous function
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool { for item in list { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } var numbers = [20, 19, 7, 12] hasAnyMatches(numbers, { num in num < 10})
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool { for item in list { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } var numbers = [20, 19, 7, 12] hasAnyMatches(numbers) { num in num < 10}
anonymous function
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool { for item in list { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } var numbers = [20, 19, 7, 12] hasAnyMatches(numbers) { $0 < 10}
anonymous function
class NamedShape { var numberOfSides: Int = 0 var name: String init(name: String) { self.name = name } func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } }
class Square: NamedShape { var sideLength: Double init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 4 } func area() -> Double { return sideLength * sideLength } override func simpleDescription() -> String { return "A square with sides of length \(sideLength)." } } !let test = Square(sideLength: 5.2, name: "my test square") test.area() test.simpleDescription()
class Square: NamedShape { var sideLength: Double init(sideLength len: Double, name: String) { self.sideLength = len super.init(name: name) numberOfSides = 4 } func area() -> Double { return sideLength * sideLength } override func simpleDescription() -> String { return "A square with sides of length \(sideLength)." } } !let test = Square(sideLength: 5.2, name: "my test square") test.area() test.simpleDescription()
class Square: NamedShape { var sideLength: Double init(_ sideLength: Double, _ name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 4 } func area() -> Double { return sideLength * sideLength } override func simpleDescription() -> String { return "A square with sides of length \(sideLength)." } } !let test = Square(5.2, "my test square") test.area() test.simpleDescription()
class EquilateralTriangle: NamedShape { var sideLength: Double = 0.0 ... var perimeter: Double { get { return 3.0 * sideLength } set { sideLength = newValue / 3.0 } } ... }
calculated properties
class TriangleAndSquare { var triangle: EquilateralTriangle { willSet { square.sideLength = newValue.sideLength } } var square: Square { willSet { triangle.sideLength = newValue.sideLength } } }
observable properties
struct Card { var rank: Rank var suit: Suit func simpleDescription() -> String { return "The \(rank.simpleDescription()) of \(suit.simpleDescription())" } } let threeOfSpades = Card(rank: Card.Three, suit: Card.Spades) let threeOfSpadesDescription = threeOfSpades.simpleDescription()
Structs
struct Card { var rank: Rank var suit: Suit func simpleDescription() -> String { return "The \(rank.simpleDescription()) of \(suit.simpleDescription())" } } let threeOfSpades = Card(rank: .Three, suit: .Spades) let threeOfSpadesDescription = threeOfSpades.simpleDescription()
Structs
classes are always passed by reference
structs are passed by reference, but automatically copied when mutated
https://www.destroyallsoftware.com/talks/boundaries
enum Rank: Int { case Ace = 1 case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten case Jack, Queen, King func simpleDescription() -> String { switch self { case .Ace: return "ace" case .Jack: return "jack" case .Queen: return "queen" case .King: return "king" default: return String(self.toRaw()) } } }
Enumerations on steroids
enum ServerResponse { case Result(String, String) case Error(String) }
Enumerations with a value associated
Enumerations with a value associated
let success = ServerResponse.Result("6:00 am", "8:09 pm") let failure = ServerResponse.Error("Out of cheese.")
Pattern matching to extract associated values
switch result { case let .Result(sunrise, sunset): let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)." case let .Error(error): let serverResponse = "Failure... \(error)" }
protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() }
Protocols... like Interface in Java or... protocols in Objective-C
extension Int: ExampleProtocol { var simpleDescription: String { return "The number \(self)" } mutating func adjust() { self += 42 } } 7.simpleDescription
extensions... like categories in Objective-C
func repeatString(item: String, times: Int) -> String[] { var result = String[]() for i in 0..times { result += item } return result } repeatString("knock", 4)
!func repeatInt(item: Int, times: Int) -> Int[] { var result = Int[]() for i in 0..times { result += item } return result } repeatInt(42, 4)
func repeat<T>(item: T, times: Int) -> T[] { var result = T[]() for i in 0..times { result += item } return result } repeat("knock", 4) repeat(42, 3)
Operator overload@infix func +(t1: Int, t2: Int) -> Int{ return 3 } !@prefix func +(t1: Int) -> Int{ return 5 } !var a = 20 var b = 111 !a + b // 3 a - +b // 15
XCTest
class RpnCalculatorKataTests: XCTestCase { override func setUp() { super.setUp() } override func tearDown() { super.tearDown() } func testExample() { XCTAssert(true, "Pass") } func testPerformanceExample() { self.measureBlock() { } } }
Quickclass PersonSpec: QuickSpec { override class func exampleGroups() { describe("Person") { var person: Person? beforeEach { person = Person() } describe("greeting") { context("when the person is unhappy") { beforeEach { person!.isHappy = false } it("is lukewarm") { expect(person!.greeting).to.equal("Oh, hi.") expect(person!.greeting).notTo.equal("Hello!") } } } } } }
enum Key : String { case One = "1" //... case Enter = "enter" case Plus = "+" case Minus = "-" } !protocol RpnCalculator { var display : String[] { get } func press(key: Key) }
https://github.com/gscalzo/RpnCalculatorKata