$30 off During Our Annual Pro Sale. View Details »

Practical Functional Programming (dotSwift 2015)

Kyle Fuller
February 06, 2015

Practical Functional Programming (dotSwift 2015)

A practical introduction to functional programming in Swift and how it can be applied to the real world. Going over what being functional means and how it allows you to write clearer, declarative and testable code.

Usually, functional programming is taught by abstract functional techniques. Instead this talk goes for a different approach showing examples of unfunctional, imperative code people may have written in the past and how that can be improved with a functional style.

Kyle Fuller

February 06, 2015
Tweet

More Decks by Kyle Fuller

Other Decks in Technology

Transcript

  1. Practical Functional
    Programming
    @kylefuller

    View Slide

  2. Imperative

    View Slide

  3. Declarative

    View Slide

  4. Describe what to do
    Not how to do it.

    View Slide

  5. What makes up functional
    programming?

    View Slide

  6. What makes up functional programming?
    4 first class functions
    4 immutable data
    4 reducing
    4 pipelining
    4 recursing
    4 currying
    4 monads

    View Slide

  7. What makes up functional programming?
    4 first class functions
    4 immutable data
    4 reducing
    4 pipelining
    4 recursing
    4 currying
    4 monads

    View Slide

  8. Side-effects

    View Slide

  9. What is not functional
    function?

    View Slide

  10. Un-functional Function
    var value = 0
    func increment() {
    value += 1
    }

    View Slide

  11. Un-functional Function
    func increment() {
    let center = NSNotificationCenter.defaultCenter()
    let value = center.valueForKey("key") as? Int ?? 0
    center.setValue(value + 1, forKey: "key")
    }

    View Slide

  12. Functional Function
    func increment(value:Int) -> Int {
    return value + 1
    }

    View Slide

  13. High Order Functions

    View Slide

  14. High Order Functions
    4 Functions that take other functions as arguments
    4 Functions that returns a functions

    View Slide

  15. Everything is a closure

    View Slide

  16. State of callables in
    Objective-C

    View Slide

  17. @implementation Object
    - (void)message:(NSString *)value {
    }
    @end

    View Slide

  18. @implementation Object
    - (void)message:(NSString *)value {
    }
    @end
    [object message:@“Hello”];

    View Slide

  19. void message(NSString *value) {
    }

    View Slide

  20. void message(NSString *value) {
    }
    message(@“Hello”);

    View Slide

  21. void (^message)(NSString *value) = ^void(NSString *value) {
    };

    View Slide

  22. View Slide

  23. void (^message)(NSString *value) = ^void(NSString *value) {
    };
    message(@“Hello”);

    View Slide

  24. Callables in Swift

    View Slide

  25. (String) -> ()

    View Slide

  26. let message:(String -> ())

    View Slide

  27. let message:(String -> ()) = { value in
    }

    View Slide

  28. func message(value:String) {
    }

    View Slide

  29. message("dotSwift")

    View Slide

  30. Interchangeability

    View Slide

  31. func message1(value:String) {
    println(“Hello \(value)”)
    }

    View Slide

  32. func message1(value:String) {
    println(“Hello \(value)”)
    }
    var message2:(String -> ()) = { value in
    println(“Hi \(value)”)
    }

    View Slide

  33. func message1(value:String) {
    println(“Hello \(value)”)
    }
    var message2:(String -> Void) = { value in
    println(“Hi \(value)”)
    }
    message2 = message1
    message2(“dotSwift”)
    // Hello dotSwift

    View Slide

  34. Functional programming by Example

    View Slide

  35. let groups = [
    ["Kyle", "Maxine"],
    ["André", "Katie", "Ash"]
    ]

    View Slide

  36. How many people are in
    each group?

    View Slide

  37. How many people are in each group?
    let groups = [["Kyle", "Maxine"], ["André", "Katie", "Ash"]]
    var count = [Int]()
    for group in groups {
    let people = countElements(group)
    count.append(people)
    }
    count
    // [2, 3]

    View Slide

  38. map

    View Slide

  39. map
    (source, transform) -> ([T])

    View Slide

  40. transform
    (item) -> (T)

    View Slide

  41. How many people are in each group?
    let groups = [["Kyle", "Maxine"], ["André", "Katie", "Ash"]]
    map(groups) {
    countElements($0)
    }
    // [2, 3]

    View Slide

  42. countElements
    (sequence) -> (Int)

    View Slide

  43. transform
    (item) -> (T)

    View Slide

  44. (item) -> (T)
    (sequence) -> (Int)

    View Slide

  45. How many people are in each group?
    let groups = [["Kyle", "Maxine"], ["André", "Katie", "Ash"]]
    map(groups, countElements)
    // [2, 3]

    View Slide

  46. Order the numbers of
    people in each group

    View Slide

  47. [2, 3] -> [3, 2]

    View Slide

  48. sorted

    View Slide

  49. sorted
    (sequence, isOrderedBefore) -> (sequence)

    View Slide

  50. isOrderedBefore
    (lhs, rhs) -> (Bool)

    View Slide

  51. Order the numbers of people in each group
    let count = [2, 3]

    View Slide

  52. Order the numbers of people in each group
    let count = [2, 3]
    sorted(count) { (lhs, rhs) in
    lhs > rhs
    }
    // largest group is [3, 2].first

    View Slide

  53. Operators are closures

    View Slide

  54. >
    (lhs, rhs) -> (Bool)

    View Slide

  55. let count = [2, 3]
    sorted(count, >)
    // largest group is [3, 2].first

    View Slide

  56. Building an array of all people

    View Slide

  57. Building an array of all people
    let groups = [["Kyle", "Maxine"], ["André", "Katie", "Ash"]]
    var people = [String]()
    for group in groups {
    people += group
    }
    // ["Kyle", "Maxine", "André", "Katie", "Ash"]

    View Slide

  58. reduce

    View Slide

  59. reduce
    (sequence, initial(U), combine) -> (U)

    View Slide

  60. combine
    (U, value) -> (U)

    View Slide

  61. +
    (U, U) -> (U)

    View Slide

  62. reduce(groups, [], +)

    View Slide

  63. Building an array of all people
    let groups = [["Kyle", "Maxine"], ["André", "Katie", "Ash"]]
    reduce(groups, [], +)
    // ["Kyle", "Maxine", "André", "Katie", "Ash"]

    View Slide

  64. let input = "Kyle,Maxine\nAndré,Katie,Ash"

    View Slide

  65. let input = "Kyle,Maxine\nAndré,Katie,Ash"
    var groups = [[String]]()
    for line in input.componentsSeparatedByString("\n") {
    let group = line.componentsSeparatedByString(",")
    groups.append(group)
    }
    groups
    // [["Kyle", "Maxine"], ["André", "Katie", "Ash"]]

    View Slide

  66. let input = "Kyle,Maxine\nAndré,Katie,Ash"
    let groups = map(input.componentsSeparatedByString("\n")) { line in
    line.componentsSeparatedByString(",")
    }
    groups
    // [["Kyle", "Maxine"], ["André", "Katie", "Ash"]]

    View Slide

  67. let input = "Kyle,Maxine\nAndré,Katie,Ash"
    func commaSeparator(input:String) -> [String] {
    return input.componentsSeparatedByString(",")
    }
    map(input.componentsSeparatedByString("\n"), commaSeparator)
    // [["Kyle", "Maxine"], ["André", "Katie", "Ash"]]

    View Slide

  68. High Order Functions
    4 Functions that returns a functions

    View Slide

  69. func separateBy(separator:String) -> ((String) -> [String]) {
    func inner(source:String) -> [String] {
    return source.componentsSeparatedByString(separator)
    }
    return inner
    }

    View Slide

  70. func separateBy(separator:String) -> ((String) -> [String]) {
    func inner(source:String) -> [String] {
    return source.componentsSeparatedByString(separator)
    }
    return inner
    }
    let lineSeparator = separateBy("\n")
    let commaSeparator = separateBy(",")

    View Slide

  71. func separateBy(separator:String)(source:String) -> [String] {
    return source.componentsSeparatedByString(separator)
    }
    let lineSeparator = separateBy("\n")
    let commaSeparator = separateBy(",")

    View Slide

  72. let input = "Kyle,Maxine\nAndré,Katie,Ash"
    map(lineSeparator(input), commaSeparator)
    // [["Kyle", "Maxine"], ["André", "Katie", "Ash"]]

    View Slide

  73. Why are map and reduce
    better?

    View Slide

  74. Declarative

    View Slide

  75. Immutability

    View Slide

  76. Don’t iterate over arrays

    View Slide

  77. Don’t iterate over arrays
    4 Use map

    View Slide

  78. Don’t iterate over arrays
    4 Use map
    4 Use reduce

    View Slide

  79. Write declaratively
    Not imperatively

    View Slide