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

Object Oriented Functional Programming — Saul Mora

Realm
June 11, 2015

Object Oriented Functional Programming — Saul Mora

Functional programming is finally a first class citizen in the Cocoa toolset! But, Swift is not necessarily a pure functional language. And in embracing the functional paradigm, do we need to throw out our knowledge and experience with Object Oriented programming? It turns out we can have our cake and eat it too!

This talk was presented at AltConf in June 2015.

Realm

June 11, 2015
Tweet

More Decks by Realm

Other Decks in Programming

Transcript

  1. map

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

    [Int] = [] for value in numbers { calculatedNumbers.append(value * 2) }
  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. 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
  6. let fileExists : (String) -> (String?) = { path in

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

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

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

    extractCreationDate { return creationDate.isBefore(NSDate.oneDayAgo()) }
  11. 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 }
  12. 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 } }
  13. 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 }
  14. protocol DataSource { func fetchItem() -> Int? } func retrieve<S:

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

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

    -> T?) -> T? { return using(from) ?? using(or) }
  17. 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) } }
  18. 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 } }
  19. 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 } }
  20. - 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.
  21. –Alan Kay Programming is at heart a practical art in

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