Slide 1

Slide 1 text

Practical Declarative Programming KyleFuller

Slide 2

Slide 2 text

Imperative Programming

Slide 3

Slide 3 text

Describe how to achieve something

Slide 4

Slide 4 text

Declarative Programming

Slide 5

Slide 5 text

Describe what to do. Not how to do it.

Slide 6

Slide 6 text

Why Declarative Programming?

Slide 7

Slide 7 text

Implementation Details

Slide 8

Slide 8 text

Simplicity

Slide 9

Slide 9 text

Constraint driven Less room for errors

Slide 10

Slide 10 text

How can we do declarative programming?

Slide 11

Slide 11 text

Domain Specific Languages (DSLs)

Slide 12

Slide 12 text

Constraints

Slide 13

Slide 13 text

Regular expressions

Slide 14

Slide 14 text

Date Regex Pattern \d\d / \d\d / \d\d\d\d

Slide 15

Slide 15 text

Date Regex Pattern Match 19 / 08 / 2015

Slide 16

Slide 16 text

SQL Structured Query Language

Slide 17

Slide 17 text

SQL Query SELECT * FROM comments WHERE author == 'Kyle'

Slide 18

Slide 18 text

NSPredicate

Slide 19

Slide 19 text

NSPredicate(format: "name == 'Kyle'")

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

Retrieve People 4 name is Kyle 4 ordered by name

Slide 22

Slide 22 text

Traditionally let fetchRequest = NSFetchRequest(entityName: "Person") fetchRequest.predicate = NSPredicate(format: "name == %@", "Kyle") fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)] var error:NSErrorPointer? var objects = managedObjectContext.executeFetchRequest(fetchRequest, error: error) if let objects = objects { ... }

Slide 23

Slide 23 text

With QueryKit Person.queryset(context) .orderBy(Person.name.ascending) .filter(Person.name == "Kyle")

Slide 24

Slide 24 text

Functional Programming

Slide 25

Slide 25 text

What makes up functional programming?

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Side-effects

Slide 29

Slide 29 text

What is not functional function?

Slide 30

Slide 30 text

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

Slide 31

Slide 31 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 32

Slide 32 text

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

Slide 33

Slide 33 text

High Order Functions

Slide 34

Slide 34 text

High Order Functions 4 Functions that take other functions as arguments

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

Everything is a function

Slide 37

Slide 37 text

State of callables in Objective-C

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

void message(NSString *value) { } In Objective-C, we can also declare functions. This may resemble the declaration method slightly from our previous examples.

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

Callables in Swift

Slide 46

Slide 46 text

(String) -> ()

Slide 47

Slide 47 text

let message:(String -> ()) We can define a constant that is callable using this syntax. It's very similar to above, we have taken the definition from the previous slide and prefixed the variable name.

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

func message(value:String) { }

Slide 50

Slide 50 text

message("AltConf")

Slide 51

Slide 51 text

Interchangeability

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

(String) -> ()

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

Functional programming by Example

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

How many people are in each group?

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

map

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

transform (item) -> (T)

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

count (sequence) -> (Int)

Slide 66

Slide 66 text

transform (item) -> (T)

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

Order the numbers of people in each group

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

sort

Slide 72

Slide 72 text

sort (sequence, isOrderedBefore) -> (sequence)

Slide 73

Slide 73 text

isOrderedBefore (lhs, rhs) -> (Bool)

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

Operators are functions

Slide 77

Slide 77 text

> (lhs, rhs) -> (Bool)

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

Building an array of all people

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

reduce

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

combine (U, T) -> (U)

Slide 84

Slide 84 text

+ (U, U) -> (U)

Slide 85

Slide 85 text

groups.reduce([], combine: +)

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

High Order Functions 4 Functions that returns a functions

Slide 92

Slide 92 text

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

Slide 93

Slide 93 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 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

Why are map and reduce better?

Slide 97

Slide 97 text

Declarative

Slide 98

Slide 98 text

Immutability

Slide 99

Slide 99 text

Performance

Slide 100

Slide 100 text

$ ./performance.swift Total time taken for 1 million iterations. Declarative: 10.7468339800835s Imperative: 12.156073987484s

Slide 101

Slide 101 text

Don’t iterate over arrays

Slide 102

Slide 102 text

Don’t iterate over arrays 4 Use map

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

Write declaratively Not imperatively

Slide 105

Slide 105 text

Conclusion 4 DSLs can be used to reduce bugs and build simpler generic declarative languages 4 We’ve seen how Functional Programming can be used to build declarative code 4 We’ve seen how declarative code helps simplicity, test-ability and on boarding new developers

Slide 106

Slide 106 text

fuller.li/360idev KyleFuller [email protected]