pooya khaloo presentation on iwmc 2015

84
A swift introduction to Giordano Scalzo Closure Busker

Upload: iran-entrepreneurship-association

Post on 17-Jul-2015

147 views

Category:

Internet


4 download

TRANSCRIPT

A swift introduction to

Giordano ScalzoClosure Busker

with different reactions

but also

From

To

What does Swift look like?

SHOW ME THE CODE!!!!!

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

Playground

Switch on steroids

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") }

Functions and closures

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)")

Functions are first class type

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

Where are the classes?

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

like classes, but passed by value...in a smarter way

classes are always passed by reference

structs are passed by reference, but automatically copied when mutated

Struct are used as ValueTypes, data components manipulated by classes

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

Generics

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

But the most important feature, the only one that you need to learn is...

Emoji!!!

For me (imvho) the most useful new features are enumerations and pattern

matching

Unit Test support

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!") } } } } } }

And now...

Let's code

a Rpn Calculator

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