Slide 1

Slide 1 text

Practical Functional Programming @kylefuller

Slide 2

Slide 2 text

Imperative

Slide 3

Slide 3 text

Declarative

Slide 4

Slide 4 text

Describe what to do Not how to do it.

Slide 5

Slide 5 text

What makes up functional programming?

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

Side-effects

Slide 9

Slide 9 text

What is not functional function?

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

High Order Functions

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

Everything is a closure

Slide 16

Slide 16 text

State of callables in Objective-C

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

void message(NSString *value) { }

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

Callables in Swift

Slide 25

Slide 25 text

(String) -> ()

Slide 26

Slide 26 text

let message:(String -> ())

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

func message(value:String) { }

Slide 29

Slide 29 text

message("dotSwift")

Slide 30

Slide 30 text

Interchangeability

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

Functional programming by Example

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

How many people are in each group?

Slide 37

Slide 37 text

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]

Slide 38

Slide 38 text

map

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

transform (item) -> (T)

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

countElements (sequence) -> (Int)

Slide 43

Slide 43 text

transform (item) -> (T)

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

Order the numbers of people in each group

Slide 47

Slide 47 text

[2, 3] -> [3, 2]

Slide 48

Slide 48 text

sorted

Slide 49

Slide 49 text

sorted (sequence, isOrderedBefore) -> (sequence)

Slide 50

Slide 50 text

isOrderedBefore (lhs, rhs) -> (Bool)

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

Operators are closures

Slide 54

Slide 54 text

> (lhs, rhs) -> (Bool)

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

Building an array of all people

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

reduce

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

combine (U, value) -> (U)

Slide 61

Slide 61 text

+ (U, U) -> (U)

Slide 62

Slide 62 text

reduce(groups, [], +)

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

High Order Functions 4 Functions that returns a functions

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

Why are map and reduce better?

Slide 74

Slide 74 text

Declarative

Slide 75

Slide 75 text

Immutability

Slide 76

Slide 76 text

Don’t iterate over arrays

Slide 77

Slide 77 text

Don’t iterate over arrays 4 Use map

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

Write declaratively Not imperatively