Pro Yearly is on sale from $80 to $50! »

James Majors: What the Swiftly Func?

1fa9cb8c7997c8c4d3d251fb5e41f749?s=47 Realm
June 08, 2017

James Majors: What the Swiftly Func?

1fa9cb8c7997c8c4d3d251fb5e41f749?s=128

Realm

June 08, 2017
Tweet

Transcript

  1. Thanks! http://bit.ly/AltConf2017

  2. This presentation doesn't contain any confidential information and isn’t intended

    only for anyone who knows anything. Any other distribution, re-transmission, copying or disclosure of this message is highly encouraged. If you have received this transmission in error, just take a few deep breaths and relax, it’s really not a big deal. If you like it, pass it on, if you don’t like it, pass it on. Thanks! What the Swiftly Func? ALTCONF 2017 Presentation Created For Anyone Who Will Listen! Created By James Majors, iOS Developer http://bit.ly/AltConf2017
  3. func iAm(_ who: Person?) -> Details { typealias Details =

    String guard let me = who else { return “Not Me!” } let whatIDo = “-> iOS Developer ” let atWhere = “@ POSSIBLE Mobile” return “\(me) \(whatIDo) \(atWhere)” } typealias Person = String let whoIAm: Person? = iAm(“James Majors”) // James Majors -> iOS Developer @ POSSIBLE Mobile
  4. What the Swiftly Func? http://bit.ly/AltConf2017

  5. Everything Old is New Again, for now… http://bit.ly/AltConf2017

  6. What is Functional Programming*? (and how to use it in

    Swift) *FP from now on…
  7. “A monad is a monoid in the category of endofunctors”

  8. “A monad is a monoid in the category of endofunctors”

    http://james-iry.blogspot.com/2009/05/brief-incomplete-and-mostly-wrong.html
  9. Functional Programming Topics • Airity • Partial Application • Idempotent

    • Functor • Lift • Referential Transparency • Lambda Calculus • Monoid • Monad • Applicative Functor • Semigroup • Setoid https://github.com/hemanth/functional-programming-jargon utm_source=hashnode.com
  10. What’s Coming Up? • Simple Definition(s) • Differences between other

    Approaches • Explain what some of the terms mean • Example of a ‘Functional’ Drawing Engine http://bit.ly/AltConf2017
  11. None
  12. FP is just another TOOL in the tool box http://bit.ly/AltConf2017

  13. None
  14. None
  15. None
  16. • Side-Effect Free • Stateless • Immutable (the Data anyway)

    Functional Programming (FP) An approach that Strives to be… http://bit.ly/AltConf2017
  17. Programming Paradigms http://bit.ly/AltConf2017

  18. Programming Approaches http://bit.ly/AltConf2017

  19. None
  20. Object-Oriented Programming • Basic Building Block = Object (variables +

    functions) class SomeClass: NSObject { var aProperty: String func doSomething() { /* Transform ‘aProperty’ */ } } • Uses LOCAL variables (state) • Changing variables (mutable data) changes state • Side-Effects are usually how things get done class SomeClass: NSObject { var aProperty: String func doSomething() { /* Transform ‘aProperty’ */ } }
  21. OK Side Effect Mutate Data Change State When you think

    of… A Button on a Screen Object
  22. None
  23. Functional Programming • Basic Building Block = Function (stateless) func

    function(value: Type) -> Type { let newValue = /* Transform ‘value’ */ return newValue } • Values (state) are passed INTO the Function • State is represented by immutable data • Side-Effects are don’t happen (Highly discouraged) func function(value: Type) -> Type { let newValue = /* Transform ‘value’ */ return newValue }
  24. + 2 2 = 4 Side Effect Mutate Data Change

    State When you think of… Adding two numbers Function
  25. What is a Function http://bit.ly/AltConf2017

  26. Function Input Output ‘Pure’ Function

  27. func squareANumber(x: Int) -> Int { return x * x

    } let squareANumber = { (x: Int) in x * x } Function: Closure Expression: Closure Expression
  28. func squareANumber(x: Int) -> Int { return x * x

    } let squareANumber = { (x: Int) in x * x } Function: Closure Expression: Function Literal
  29. Closure: Function with out a name a.k.a. Anonymous Function Function:

    Closure with a name
  30. Closure Anonymous Function Block Inline Function Lambda Expression

  31. Side-Effect Free http://bit.ly/AltConf2017

  32. Functional Function Input Output ‘Pure’ Function

  33. OOP Function Input

  34. OOP Function Input OBJ

  35. OOP Function Input OBJ OBJ OBJ OBJ OBJ OBJ OBJ

    OBJ
  36. OOP Function Input Output OBJ OBJ OBJ OBJ OBJ OBJ

    OBJ OBJ
  37. ‘add’ Function Input 4 Output (2, 2) func add(_ lhs:

    Int, _ rhs: Int) -> Int add(2, 2)
  38. State or the lack thereof… http://bit.ly/AltConf2017

  39. The value of ALL VARIABLES in an Object* at any

    instant in time http://bit.ly/AltConf2017
  40. class ShapeClass { var shape: Shape var lineColor: Color var

    fillColor: Color } 3 Choices 3 Choices 3 Choices 27 POSSIBLE STATES
  41. OBJ OBJ OBJ OBJ OBJ OBJ OBJ OBJ

  42. Non-Mutable Data http://bit.ly/AltConf2017

  43. Once a value is set, it CAN NOT be changed.

    http://bit.ly/AltConf2017
  44. var value: Int = 10 value = 30 value =

    50
  45. let value: Int = 10

  46. Want to change it? http://bit.ly/AltConf2017

  47. Want to change it? Make a new one… http://bit.ly/AltConf2017

  48. let numbersArray: [Int] init(numbers: [Int]) { numbersArray = numbers }

    func add(number: Int) -> NumbersStruct { var newArray = Array(numbersArray) newArray.append(number) return NumbersStruct(numbers: newArray) } struct NumbersStruct { } }
  49. Value Types not References Type http://bit.ly/AltConf2017

  50. Value

  51. Reference

  52. Value: Swift Types enum struct class Array Dictionary Reference: func

  53. • Side-Effect Free • Stateless • Uses Immutable Data Functional

    Programming (FP) More or less(ish) http://bit.ly/AltConf2017
  54. Functions as ‘First-Class’ Type http://bit.ly/AltConf2017

  55. func squareANumber(x: Int) -> Int { return x * x

    } let squareAnInt = { (x: Int) in x * x } let squareInt = squareAnInt Type: Closure Type: Closure let aNumber = 25
  56. func squareANumber(x: Int) -> Int { return x * x

    } func doSomething(x: Int, function: ((Int) -> Int)) -> Int { -> Int { Type: Closure Type: func doubleANumber(x: Int) -> Int { return x + x } } return function(x) Type: Apply Function to ‘x’
  57. func squareANumber(x: Int) -> Int { return x * x

    } func doSomething(x: Int, function: ((Int) -> Int)) -> Int { -> Int { func doubleANumber(x: Int) -> Int { return x + x } } return function(x) doSomething(x: 10, function: squareANumber) // 100
  58. func squareANumber(x: Int) -> Int { return x * x

    } func doSomething(x: Int, function: ((Int) -> Int)) -> Int { -> Int { func doubleANumber(x: Int) -> Int { return x + x } } return function(x) doSomething(x: 10, function: squareANumber) // 100 doSomething(x: 10, function: doubleANumber) // 20
  59. func doSomething(x: Int, function: ((Int) -> Int)) -> Int {

    Type: } return function(x) Type: Type: Closure
  60. } x * x func doSomething(x: Int, function: ((Int) ->

    Int)) -> Int { Type: Closure Type: } return function(x) let doSomething(x: 10 { (x: Int) in ) , function: Type: Type: Closure return func squareANumber(x: Int) -> Int { return x * x } doSomething(x: 10, function: squareANumber)
  61. } x * x func doSomething(x: Int, function: ((Int) ->

    Int)) -> Int { Type: } return function(x) let doSomething(x: 10 { (x: Int) in ) Type: Type: Closure return func squareANumber(x: Int) -> Int { return x * x } doSomething(x: 10, function: squareANumber)
  62. } x * x func doSomething(x: Int, function: ((Int) ->

    Int)) -> Int { Type: } return function(x) let doSomething(x: 10 { (x: Int) in ) Type: Type: Closure func squareANumber(x: Int) -> Int { return x * x } doSomething(x: 10, function: squareANumber)
  63. } x * x func doSomething(x: Int, function: ((Int) ->

    Int)) -> Int { Type: } return function(x) let doSomething(x: 10 // = 100 { (x: Int) in ) Type: Type: Closure Trailing Closure Syntax func squareANumber(x: Int) -> Int { return x * x } doSomething(x: 10, function: squareANumber)
  64. func doWhat(x: Int) -> ((Int) -> Int) { Type: Closure

    Type: } doWhat
  65. func squareANumber(x: Int) -> Int { return x * x

    } func doWhat(x: Int) -> ((Int) -> Int) { func doubleANumber(x: Int) -> Int { return x + x } } Inner Functions doWhat
  66. func squareANumber(x: Int) -> Int { return x * x

    } func doWhat(x: Int) -> ((Int) -> Int) { func doubleANumber(x: Int) -> Int { return x + x } } if x % 2 == 0 { return squareANumber } else { return doubleANumber } doWhat squareANumber doubleANumber
  67. func doWhat(x: Int) -> ((Int) -> Int) { } if

    x % 2 == 0 { return squareANumber } else { return doubleANumber } let squareANumber = { (x: Int) in x * x } let doubleANumber = { (x: Int) in x + x } doWhat { (x: Int) in x + x } { (x: Int) in x * x } squareANumber doubleANumber
  68. squareIt(5) // = 25 func doWhat(x: Int) -> ((Int) ->

    Int) { } if x % 2 == 0 { return squareANumber } else { return doubleANumber } let squareIt = doWhat(x: 2) let doubleIt = doWhat(x: 3) doubleIt(5) // = 10 doWhat { (x: Int) in x + x } { (x: Int) in x * x }
  69. Function take a Function as an argument Function return a

    Function Closure Closure http://bit.ly/AltConf2017
  70. Higher-Order Functions http://bit.ly/AltConf2017

  71. Higher-Order Functions Function that takes a Function as an argument

    Function that returns a Function Function that takes and returns a Function
  72. IntFunc func takeFunction(x: Int, function: return function(x) } func returnFunction(x:

    Int) -> if x % 2 == 0 { return { (x: Int) in x + x } } else { return { (x: Int) in x * x } } } typealias IntFunc = (Int) -> Int ) -> Int { { ((Int) -> Int)
  73. IntFunc func takeFunction(x: Int, function: return function(x) } func returnFunction(x:

    Int) -> if x % 2 == 0 { return { (x: Int) in x + x } } else { return { (x: Int) in x * x } } } typealias IntFunc = (Int) -> Int ) -> Int { { IntFunc
  74. Map http://bit.ly/AltConf2017

  75. Map func map<T, U>( function: (T) -> U) -> [U]

  76. Map func map<T, U>( function: (T) -> U) -> [U]

    let new = [1,2,3,4,5].map { 10 * $0 }
  77. Function [Array] [Results] { 10 * number } { 10

    * number } { 10 * number } { 10 * number } { 10 * } { 10 * } { 10 * } { 10 * } { 10 * } 1 2 3 4 5 [ , , , , ]
  78. Function [Array] [Results] 10 { 10 * number } {

    10 * number } { 10 * number } { 10 * number } { 10 * } { 10 * } { 10 * } { 10 * } { 10 * } = 1 2 3 4 5 [ , , , , ]
  79. Function [Array] [Results] 10 { 10 * } { 10

    * } { 10 * } { 10 * } { 10 * } = 20 = 30 = 40 = 50 = 1 2 3 4 5 [ , , , , ] 10 20 30 40 50
  80. Map func map<T, U>( function: (T) -> U) -> [U]

    ‘Generic’ Types
  81. Map func map<T, U>( function: (T) -> U) -> [U]

    let new = [1,2,3,4,5].map { 10 * $0 } Positional Argument (i.e. Function’s first Argument)
  82. Map func map<T, U>( function: (T) -> U) -> [U]

    let new = [1,2,3,4,5].map { 10 * $0 } // new = [10,20,30,40,50]
  83. Generic Types

  84. func map<T, U>(function: (T) -> U) -> [U] Generic Types

  85. func map<InputType, U>(function: (InputType) -> U) -> [U] Generic Types

  86. func map<T, OutputType>(function: (T) -> OutputType) -> [OutputType] Generic Types

  87. func map<InputType, OutputType>(function: (InputType) -> OutputType) -> [OutputType] Generic Types

  88. func map<AType, BType>(function: (AType) -> BType) -> [BType] Generic Types

  89. func map<Int, U>(function: (Int) -> U) -> [U] Generic Types

  90. func map<Int, Int>(function: (Int) -> Int) -> [Int] Generic Types

  91. func map<Int, String>(function: (Int) -> String) -> [String] Generic Types

  92. func map<String, Int>(function: (String) -> Int) -> [Int] Generic Types

  93. func map<T, U>(function: (T) -> U) -> [U] Generic Types

  94. T = Some Type func map<T, U>(function: (T) -> U)

    -> [U] Int, Float, String, class, struct… Generic Types
  95. T = Some Type U = Some Type func map<T,

    U>(function: (T) -> U) -> [U] Int, Float, String, class, struct… Int, Float, String, class, struct… Generic Types
  96. Filter http://bit.ly/AltConf2017

  97. Filter func filter<T>(function: (T) -> Bool) -> [T] let new

    = [1,2,3,4,5].filter { $0 % 2 == 0 }
  98. Function [Array] [Results] { x % 2 == 0 }

    { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } 1 2 3 4 5 [ , ]
  99. Function [Array] [Results] { x % 2 == 0 }

    { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } 2 3 4 5 [ , ] 1
  100. Function [Array] [Results] false { x % 2 == 0

    } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } = 2 3 4 5 [ , ] 1
  101. Function [Array] [Results] { x % 2 == 0 }

    { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } 2 3 4 5 [ , ]
  102. Function [Array] [Results] { x % 2 == 0 }

    { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } 3 4 5 [ , ] 2
  103. Function [Array] [Results] { x % 2 == 0 }

    { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } { x % 2 == 0 } true = 3 4 5 [ , ] 2
  104. Function [Array] [Results] [ , ] 2 4 2 4

  105. Filter

  106. Filter func filter<T>(function: (T) -> Bool) -> [T]

  107. Filter let new = [1,2,3,4,5].filter { $0 % 2 ==

    0 } func filter<T>(function: (T) -> Bool) -> [T]
  108. Filter let new = [1,2,3,4,5].filter { $0 % 2 ==

    0 } // new = [2,4] func filter<T>(function: (T) -> Bool) -> [T]
  109. Reduce http://bit.ly/AltConf2017

  110. Reduce

  111. Reduce func reduce<T>( initialValue: T, function: (T, T) -> T)

    -> T
  112. { $0 + $1 } Reduce func reduce<T>( initialValue: T,

    function: (T, T) -> T) -> T let new = [1,2,3,4,5].reduce(0, + )
  113. { $0 + $1 } Reduce func reduce<T>( initialValue: T,

    function: (T, T) -> T) -> T let new = [1,2,3,4,5].reduce(0, + ) Acc. Acc.
  114. { $0 + $1 } Reduce func reduce<T>( initialValue: T,

    function: (T, T) -> T) -> T let new = [1,2,3,4,5].reduce(0, + ) [Element] Acc. [Element] Acc.
  115. { $0 + $1 } Reduce func reduce<T>( initialValue: T,

    function: (T, T) -> T) -> T let new = [1,2,3,4,5].reduce(0, + )
  116. Reduce func reduce<T>( initialValue: T, function: (T, T) -> T)

    -> T let new = [1,2,3,4,5].reduce(0, + )
  117. Result [ , , , , ] 1 2 3

    4 5 Function [Array] Accumulator Initial Value + } { x acc Acc Init
  118. Result [ , , , , ] 1 2 3

    4 5 Function [Array] + } { x acc Acc Init =
  119. Result [ , , , , ] 1 2 3

    4 5 Function [Array] + } { x acc = 0 0
  120. Result + } 1 2 3 4 5 Function [Array]

    { x acc + } { x acc 0
  121. Result + } 1 2 3 4 5 Function [Array]

    { = 1 0
  122. { $0 + $1 } Reduce func reduce<T>( initialValue: T,

    function: (T, T) -> T) -> T let new = [1,2,3,4,5].reduce(0, + ) [Element] Acc. [Element] Acc.
  123. Reduce func reduce<T>( initialValue: T, function: (T, T) -> T)

    -> T let new = [1,2,3,4,5].reduce(0, + ) // new = 15
  124. Imperative vs. Declarative ‘How To Do Something’ vs. ‘What You

    Want Done’ http://bit.ly/AltConf2017
  125. Imperative Programming describes the algorithm http://bit.ly/AltConf2017

  126. func arrayTimesTen(array: [Int]) -> [Int] { var outputArray = [Int]()

    for number in array { var newNumber = number * 10 outputArray.append(newNumber) } return outputArray } var outputArray = [Int]() for number in array { var newNumber = number * 10 outputArray.append(newNumber) } let newNumber = number * 10 outputArray.append(newNumber) return outputArray number * 10
  127. func arrayTimesTen(array: [Int]) -> [Int] { var outputArray = [Int]()

    for number in array { var newNumber = number * 10 outputArray.append(newNumber) } return outputArray } var outputArray = [Int]() for number in array { var newNumber = number * 10 outputArray.append(newNumber) } let newNumber = number * 10 outputArray.append(newNumber) return outputArray number * 10
  128. Declarative Programming describes the result http://bit.ly/AltConf2017

  129. let mapped = array.map { $0 * 10 } let

    array = [1,2,3,4,5]
  130. let mapped = array.map { $0 * 10 } let

    filtered = array.filter { $0 % 2 == 0 } let array = [1,2,3,4,5]
  131. let mapped = array.map { $0 * 10 } let

    filtered = array.filter { $0 % 2 == 0 } let array = [1,2,3,4,5]
  132. let mapped = array.map { $0 * 10 } let

    filtered = array.filter { $0 % 2 == 0 } let reduced = array.reduce(0, + ) let array = [1,2,3,4,5]
  133. let mapped = array.map { $0 * 10 } let

    filtered = array.filter { $0 % 2 == 0 } let reduced = array.reduce(0, + ) let array = [1,2,3,4,5]
  134. let mapIt = [1,2,3,4,5].map(timesTen) func timesTen(x: Int) -> Int {

    return x * 10 }
  135. let mapIt = [1,2,3,4,5].map(timesTen) let filterIt = [1,2,3,4,5].filter(isEven) func timesTen(x:

    Int) -> Int { return x * 10 } func isEven(x: Int) -> Bool { return x % 2 == 0 }
  136. let mapIt = [1,2,3,4,5].map(timesTen) let filterIt = [1,2,3,4,5].filter(isEven) func timesTen(x:

    Int) -> Int { return x * 10 } func isEven(x: Int) -> Bool { return x % 2 == 0 } let addIt = [1,2,3,4,5].reduce(0, add) func add(x: Int, y: Int) -> Int { return x + y }
  137. Currying http://bit.ly/AltConf2017

  138. ‘Partial Application’ of a Function http://bit.ly/AltConf2017

  139. of a Function ‘Initialization’ http://bit.ly/AltConf2017

  140. func addClosure(x: Int) -> ((Int) -> Int) { return {

    y in x * y } } let add = addClosure(x: 10) add(10) // 100 x x
  141. func addClosure(x: Int) -> ((Int) -> Int) { return {

    y in x * y } } let add = addClosure(x: 10) add(100) // 1000 add(10) // 100 x x
  142. ((col or: Color) -> DrawingItem) func itemWith(shape: Shape, color: Color)

    -> DrawingItem { return DrawingItem(shape: shape, color: color) } func someShape(shape: Shape) -> } (_ color: Color) -> DrawingItem { return { color in return itemWith(shape: shape, color: color) } shape color shape color { } let ovalShape = someShape(shape: .oval) let triangleShape = someShape(shape: .triangle) let blackOval = ovalShape(.black) let whiteTriangle = triangleShape(.white) return itemWith(shape: shape, color: color) itemWith
  143. Functional Drawing Engine http://bit.ly/AltConf2017

  144. Go forth and be Func’y! http://bit.ly/AltConf2017

  145. This presentation doesn't contain any confidential information and isn’t intended

    only for anyone who knows anything. Any other distribution, re-transmission, copying or disclosure of this message is highly encouraged. If you have received this transmission in error, just take a few deep breaths and relax, it’s really not a big deal. If you like it, pass it on, if you don’t like it, pass it on. Thanks! What the Swiftly Func? ALTCONF 2017 Presentation Created For Anyone Who Will Listen! Created By James Majors, iOS Developer http://bit.ly/AltConf2016
  146. Thanks! http://bit.ly/AltConf2017