Slide 1

Slide 1 text

Object Oriented Functional Programming Saul Mora [email protected] @casademora

Slide 2

Slide 2 text

Functional Object Oriented Programming Saul Mora [email protected] @casademora

Slide 3

Slide 3 text

Programming Oriented Functional Object Saul Mora [email protected] @casademora

Slide 4

Slide 4 text

Objects

Slide 5

Slide 5 text

C++ Objective C C# Java Ruby Python Javascript PHP

Slide 6

Slide 6 text

Scala Clojure Swift

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Will it blend

Slide 9

Slide 9 text

What a Functional Language is NOT

Slide 10

Slide 10 text

Statically Typed

Slide 11

Slide 11 text

Generics

Slide 12

Slide 12 text

Overloaded Operators

Slide 13

Slide 13 text

Optionals

Slide 14

Slide 14 text

A language where functions are value types

Slide 15

Slide 15 text

Objective C is a Functional Language

Slide 16

Slide 16 text

F(x) = y

Slide 17

Slide 17 text

f(x: Int) -> Int

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

map

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

let numbers = [1, 2, 3, 4, 5] var calculatedNumbers: [Int] = [] for value in numbers { calculatedNumbers.append(value * 2) }

Slide 24

Slide 24 text

let numbers = [1, 2, 3, 4, 5] let calculatedNumbers = map(numbers) { $0 * 2 }

Slide 25

Slide 25 text

Declarative vs. Imperative

Slide 26

Slide 26 text

What vs. How

Slide 27

Slide 27 text

Deep Dive

Slide 28

Slide 28 text

func old_and_busted_expired(fileURL: NSURL) -> Bool

Slide 29

Slide 29 text

func old_and_busted_expired(fileURL: NSURL) -> Bool { let fileManager = NSFileManager() if let filePath = fileURL.path { if fileManager.fileExistsAtPath(filePath) { var error: NSError? let fileAttributes = fileManager.attributesOfItemAtPath(filePath, error: &error) if let fileAttributes = fileAttributes { if let creationDate = fileAttributes[NSFileModificationDate] as? NSDate { return creationDate.isBefore(NSDate.oneDayAgo()) } } else { NSLog("No file attributes \(filePath)") } } } return false }

Slide 30

Slide 30 text

let fileManager = NSFileManager() if let filePath = fileURL.path { if fileManager.fileExistsAtPath(filePath) { var error: NSError? let fileAttributes = fileManager.attributesOfItemAtPath(filePath, error: &error) if let fileAttributes = fileAttributes { if let creationDate = fileAttributes[NSFileModificationDate] as? NSDate { return creationDate .isBefore(NSDate.oneDayAgo()) } } else { NSLog("No file attributes \(filePath)") } }

Slide 31

Slide 31 text

unwrapping the file path check if the file exists extract and unwrap the file attributes extract, unwrap and cast the NSModifiedDateAttribute compute one day ago return comparison to file last modified date

Slide 32

Slide 32 text

let filePath = fileURL.path

Slide 33

Slide 33 text

let fileExists : (_) -> (_)

Slide 34

Slide 34 text

let fileExists : (String) -> (String?)

Slide 35

Slide 35 text

let fileExists : (String) -> (String?) = { path in fileManager.fileExistsAtPath(path) ? path : nil }

Slide 36

Slide 36 text

let retrieveFileAttributes : (_) -> (_)

Slide 37

Slide 37 text

let retrieveFileAttributes : (String) -> ([NSObject: AnyObject]?)

Slide 38

Slide 38 text

let retrieveFileAttributes : (String) -> ([NSObject: AnyObject]?) = { path in var error : NSError? let attributes = fileManager.attributesOfItemAtPath(path, error: &error) if attributes == nil { NSLog("Unable to check \(filePath): \(error)") } return attributes }

Slide 39

Slide 39 text

let extractCreationDate : (_) -> (_)

Slide 40

Slide 40 text

let extractCreationDate : ([NSObject:AnyObject]) -> (NSDate?)

Slide 41

Slide 41 text

let extractCreationDate : [NSObject:AnyObject] -> NSDate? = { $0[NSFileModificationDate] as? NSDate }

Slide 42

Slide 42 text

let filePath: String? let fileExists: String -> String? let extractFileAttributes: String -> [NSObject:AnyObject]? let extractCreationDate: [NSObject:AnyObject] -> NSDate?

Slide 43

Slide 43 text

Composition

Slide 44

Slide 44 text

bind

Slide 45

Slide 45 text

bind(A?, f(A) -> B?) -> B?

Slide 46

Slide 46 text

func bind(a: A?, f: A -> B?) -> B? { if let x = a { return f(x) } else { return .None } }

Slide 47

Slide 47 text

bind(filePath, fileExists)

Slide 48

Slide 48 text

bind(bind(filePath, fileExists), retrieveFileAttributes)

Slide 49

Slide 49 text

bind(bind(bind(filePath, fileExists), retrieveFileAttributes), extractCreationDate)

Slide 50

Slide 50 text

let creationDate: NSDate? = bind(bind(bind(filePath, fileExists), retrieveFileAttributes), extractCreationDate)

Slide 51

Slide 51 text

>>= operator

Slide 52

Slide 52 text

func >>=(a: A?, f: A -> B?) -> B? { return bind(a, f) }

Slide 53

Slide 53 text

bind(filePath, fileExists)

Slide 54

Slide 54 text

filePath >>= fileExists

Slide 55

Slide 55 text

if let creationDate = filePath >>= fileExists >>= retrieveFileAttributes >>= extractCreationDate { return creationDate.isBefore(NSDate.oneDayAgo()) }

Slide 56

Slide 56 text

let checkExpired: NSDate -> Bool? = { $0.isBefore(NSDate.oneDayAgo()) }

Slide 57

Slide 57 text

return filePath >>= fileExists >>= retrieveFileAttributes >>= extractCreationDate >>= checkExpired ?? false

Slide 58

Slide 58 text

func expired(fileURL: NSURL) -> Bool { let fileManager = NSFileManager() var error : NSError? let filePath = fileURL.path let fileExists : (String) -> (String?) = { path in fileManager.fileExistsAtPath(path) ? path : nil } let retrieveFileAttributes : (String) -> ([NSObject: AnyObject]?) = { path in var error : NSError? return fileManager.attributesOfItemAtPath(path, error: &error) } let extractCreationDate : ([NSObject:AnyObject]) -> NSDate? = { $0[NSFileModificationDate] as? NSDate } let checkExpired: NSDate -> Bool? = { $0.isBefore(NSDate.oneDayAgo()) } return filePath >>= fileExists >>= retrieveFileAttributes >>= extractCreationDate >>= checkExpired ?? false }

Slide 59

Slide 59 text

Railway Oriented Programming fsharpforfunandprofit.com/posts/recipe-part2/

Slide 60

Slide 60 text

Readability

Slide 61

Slide 61 text

bind flatMap (fmap) apply >>= >>- <^> <$> <*>

Slide 62

Slide 62 text

func <^>(f: A -> B, a: A?) -> B? { return fmap(f, a) } func fmap(f: A -> B, a: A?) -> B? { if let x = a { return f(x) } else { return .None } }

Slide 63

Slide 63 text

func <*>(f: (A -> B)?, a: A?) -> B? { return apply(f, a) } func apply(f: (A -> B)?, a: A?) -> B? { if let x = a, let fx = f { return fx(x) } return .None }

Slide 64

Slide 64 text

Argo http://github.com/thoughtbot/Argo

Slide 65

Slide 65 text

What about objects?

Slide 66

Slide 66 text

Objects > Functions

Slide 67

Slide 67 text

Objects ≈ Functions

Slide 68

Slide 68 text

Caching

Slide 69

Slide 69 text

retrieve

Slide 70

Slide 70 text

Data Client RemoteDataSource LocalDataSource

Slide 71

Slide 71 text

Data Client RemoteDataSource LocalDataSource

Slide 72

Slide 72 text

Data Client RemoteDataSource LocalDataSource DataSourceCache

Slide 73

Slide 73 text

Data Client RemoteDataSource LocalDataSource DataSourceCache Cache Strategy

Slide 74

Slide 74 text

Strategy

Slide 75

Slide 75 text

protocol DataSource { func fetchItem() -> Int? } func retrieve(from: S, or: S) -> T? { return from.fetchItem() ?? or.fetchItem() }

Slide 76

Slide 76 text

protocol DataSource { func fetchItem() -> Int? } func retrieveItem(from: S, or: S) -> T? { return from.fetchItem() ?? or.fetchItem() }

Slide 77

Slide 77 text

from.fetchItem()

Slide 78

Slide 78 text

from .fetchItem() Object Instance Selector

Slide 79

Slide 79 text

func retrieve (from: S, or: S, using: S -> T?) -> T? { return using(from) ?? using(or) }

Slide 80

Slide 80 text

let localDataSource: DataSource let remoteDataSource: DataSource return retrieve(from: localDataSource, or: remoteDataSource) { $0.fetchItem() }

Slide 81

Slide 81 text

protocol DataSourceCacheStrategy { func retrieve(from: [DataSource], using: DataSource -> T?) -> T? } struct DataSourceCache { let strategy: DataSourceCacheStrategy let localDataSource: DataSource let remoteDataSource: DataSource func fetch(applyFunction: DataSource -> T?) -> T? { let sources = [localDataSource, remoteDataSource] return strategy.retrieve(sources, using: applyFunction) } }

Slide 82

Slide 82 text

struct BasicDataSourceCacheStrategy: DataSourceCacheStrategy { func retrieve(from: [DataSource], using: DataSource -> T?) -> T? { for dataSource in from { if let result = using(dataSource) { return result } } return nil } }

Slide 83

Slide 83 text

struct MoreFancyDataSourceCacheStrategy: DataSourceCacheStrategy { func retrieve(from: [DataSource], using: DataSource -> T?) -> T?{ let cacheValidation: T? -> Bool = { $0 != nil } for dataSource in from { let result = using(dataSource) if cacheValidation(result) { return result } } return nil } }

Slide 84

Slide 84 text

Encapsulation

Slide 85

Slide 85 text

Abstraction

Slide 86

Slide 86 text

SOLID

Slide 87

Slide 87 text

Object Oriented in the Large, Functional in the Small

Slide 88

Slide 88 text

Stuff that changes vs. Stuff that doesn’t

Slide 89

Slide 89 text

Functional Friendly Problem Domains

Slide 90

Slide 90 text

- Alan Kay, The Early History of Smalltalk I was less interested in programs as algebraic patterns than I was in a clear scheme that could handle a variety of styles of programming.

Slide 91

Slide 91 text

Object Oriented Programming Functional Programming

Slide 92

Slide 92 text

Programming Object Oriented Programming Functional Programming

Slide 93

Slide 93 text

–Alan Kay Programming is at heart a practical art in which real things are built, and a real implementation thus has to exist.

Slide 94

Slide 94 text

Object Oriented Functional Programming Saul Mora [email protected] @casademora