Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ITT 2015 - Saul Mora - Object Oriented Function...

ITT 2015 - Saul Mora - Object Oriented Function Programming

Functional programming is finally a first class citizen in the Cocoa toolset! But, as you may have heard, Swift is not necessarily a pure functional language. And in embracing the functional paradigm, do you need to throw out your knowledge and experience with Object Oriented programming? Saul Mora shows that it turns out you can have your cake and eat it too!

Istanbul Tech Talks

April 27, 2015
Tweet

More Decks by Istanbul Tech Talks

Other Decks in Programming

Transcript

  1. let numbers = [1, 2, 3, 4, 5] var calculatedNumbers:

    [Int] = [] for value in numbers { calculatedNumbers.append(value * 2) }
  2. map

  3. 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 }
  4. ! 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)") } }
  5. ! 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)") } }
  6. 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
  7. let fileExists : (String) -> (String?) = { path in

    fileManager.fileExistsAtPath(path) ? path : nil }
  8. 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 }
  9. let filePath: String? let fileExists: String -> String? let extractFileAttributes:

    String -> [NSObject:AnyObject]? let extractCreationDate: [NSObject:AnyObject] -> NSDate?
  10. func bind<A, B>(a: A?, f: A -> B?) -> B?

    { if let x = a { return f(x) } else { return .None } }
  11. if let creationDate = filePath >>= fileExists >>= retrieveFileAttributes >>=

    extractCreationDate { return creationDate.isBefore(NSDate.oneDayAgo()) }
  12. 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 }
  13. func <^><A, B>(f: A -> B, a: A?) -> B?

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

    { return apply(f, a) } ! func apply<A, B>(f: (A -> B)?, a: A?) -> B? { if let x = a, let fx = f { return fx(x) } return .None }
  15. protocol DataSource { func fetchItem() -> Int? } ! func

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

    retrieveItem<S: DataSource, T>(from: S, or: S) -> T? { return from.fetchItem() ?? or.fetchItem() }
  17. ! func retrieve<S: DataSource, T> (from: S, or: S, using:

    S -> T?) -> T? { return using(from) ?? using(or) }
  18. protocol DataSourceCacheStrategy { func retrieve<T>(from: [DataSource], using: DataSource -> T?)

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

    T?) -> T? { for dataSource in from { if let result = using(dataSource) { return result } } return nil } }
  20. struct MoreFancyDataSourceCacheStrategy: DataSourceCacheStrategy { ! func retrieve<T>(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 } }
  21. - 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.
  22. –Alan Kay Programming is at heart a practical art in

    which real things are built, and a real implementation thus has to exist.