Upload
istanbul-tech-talks
View
113
Download
1
Embed Size (px)
Citation preview
Objects
C++
Objective C
C#
Java
RubyPython
Javascript PHP
Scala!
Clojure!
Swift
Will it blend
What a Functional Language is NOT
Statically Typed
Generic
Overloaded Operators
Optionals
A language where functions are value types
F(x) = y
f(x: Int) -> Int
let numbers = [1, 2, 3, 4, 5]var calculatedNumbers: [Int] = []for value in numbers { calculatedNumbers.append(value * 2)}
map
let numbers = [1, 2, 3, 4, 5]let calculatedNumbers = map(numbers) { $0 * 2 }
Declarative vs. Imperative
What vs. How
Deep Dive
func old_and_busted_expired(fileURL: NSURL) -> Bool
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}
!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 creationDate.isBefore(NSDate.oneDayAgo())
!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)") } }}
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
let filePath = fileURL.path
let fileExists : (_) -> (_)
let fileExists : (String) -> (String?)
let fileExists : (String) -> (String?) ={ path in
fileManager.fileExistsAtPath(path) ? path : nil
}
let retrieveFileAttributes : (_) -> (_)
let retrieveFileAttributes : (String) -> ([NSObject: AnyObject]?)
let retrieveFileAttributes : (String) -> ([NSObject: AnyObject]?) = { path invar error : NSError?let attributes = fileManager.attributesOfItemAtPath(path, error: &error)
!if attributes == nil {NSLog("Unable to check \(filePath): \(error)")
}return attributes
}
let extractCreationDate : (_) -> (_)
let extractCreationDate : ([NSObject:AnyObject]) -> (NSDate?)
let extractCreationDate : [NSObject:AnyObject] -> NSDate? = { $0[NSFileModificationDate] as? NSDate }
filePath: String?
fileExists: String -> String?
extractFileAttributes: String -> [NSObject:AnyObject]?
extractCreationDate: [NSObject:AnyObject] -> NSDate?
let filePath: String?
let fileExists: String -> String?
let extractFileAttributes: String -> [NSObject:AnyObject]?
let extractCreationDate: [NSObject:AnyObject] -> NSDate?
bind
bind(A?, f(A,B?)) -> B?
func bind<A, B>(a: A?, f: A -> B?) -> B? { if let x = a { return f(x) } else { return .None }}
bind(filePath, fileExists)
bind(bind(filePath, fileExists), retrieveFileAttributes)
bind(bind(bind(filePath, fileExists), retrieveFileAttributes), extractCreationDate)
let creationDate: NSDate? = bind(bind(bind(filePath, fileExists), retrieveFileAttributes), extractCreationDate)
>>= operator
func >>=<A, B>(a: A?, f: A -> B?) -> B? { return bind(a, f)}
bind(filePath, fileExists)
filePath >>= fileExists
if let creationDate = filePath >>= fileExists >>= retrieveFileAttributes >>= extractCreationDate { return creationDate.isBefore(NSDate.oneDayAgo())}
let checkExpired: NSDate -> Bool? = { $0.isBefore(NSDate.oneDayAgo()) }
return filePath >>= fileExists >>= retrieveFileAttributes >>= extractCreationDate >>= checkExpired ?? false
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}
Readability
bind!
flatMap (fmap)!
apply
>>= (>>-)!
<^> (<$>)!
<*>
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 }}
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}
Argohttp://github.com/thoughtbot/Argo
What about objects?
Caching
retrieve
protocol DataSource { func fetchItem() -> Int?}!func retrieve<S: DataSource, T>(from: S, or: S) -> T? { return from.fetchItem() ?? or.fetchItem()}
protocol DataSource { func fetchItem() -> Int?}!func retrieveItem<S: DataSource, T>(from: S, or: S) -> T? { return from.fetchItem() ?? or.fetchItem()}
return <DataSource>!.functionCall()! -> Int?
!func retrieve<S: DataSource, T>
(from: S, or: S, using: S -> T?) -> T?{ return using(from) ?? using(or)}
let localDataSource: DataSourcelet remoteDataSource: DataSourcereturn retrieve(from: localDataSource, or: remoteDataSource) { $0.fetchItem() }
Data Client
RemoteDataSource
LocalDataSource
Data Client
RemoteDataSource
LocalDataSource
Data Client
RemoteDataSource
LocalDataSource
DataSourceCache
Data Client RemoteDataSource
LocalDataSource
DataSourceCache
Cache Strategy
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) } }
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 } }
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 } }
https://gist.github.com/casademora/
3b784e57bd09c0bc9147
Encapsulation
Abstraction
SOLID
Object Oriented in the Large, Functional in the
Small
- 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.
Programming
–Alan Kay
Programming is at heart a practical art in which real things are built, and a real implementation
thus has to exist.