Upload
tales-andrade
View
240
Download
2
Embed Size (px)
Citation preview
Quem sou eu
• Mestre em Computação pelo IME-USP• Desenvolvedor C desde 2002• Objective-C desde 2007 (coisas básicas em Mac OS X antes do
iPhone!)• iOS desde 2010• Swift desde Agosto/2015• Tech Lead na Concrete Solutions (estamos contratando)• Organizador do CocoaHeads SP• Colaborador do CocoaHeads BR• Colaborador da Embaixada Brasileira de Appsterdam
Compartilhando código e dependências entre plataformas
Escrevendo uma vez e reutilizando em iOS, tvOS, watchOS, macOS 😂
Ou…
…veja bem…
Como alterei o tema da minha palestra
E esqueci de enviar a atualização
Usando POP com Programação Funcional
Como entender algumas abstrações usando Protocol Oriented Programming
A Formula
• Descreva em linguagem natural• Escreva a assinatura do tipo• Implemente a logica• Teste seu código(não necessariamente nessa ordem)
O que é programação funcional?
• Estilo de programação• First Class Functions• Modularização• Efeitos colaterais• Imutabilidade
O que é programação funcional?
A monad is just a monoid in the category of endofunctors, what's the problem?
Crockford’s Law
In addition to its being good and useful, it's also cursed. The curse ofthe monad is that once you get the epiphany, once you understand oh, that's what it is, you lose the ability to explain it to anybody else.
Três protocolos/conceitos
protocol Concattable { init() func +(left: Self, right: Self) -> Self static func concat(list: [Self]) -> Self}
extension Concattable { static func concat(list: [Self]) -> Self { return list.reduce(Self(), combine: +) }}
extension Int: Concattable {}extension Float: Concattable {}extension String: Concattable {}extension Array: Concattable {}
func +<T>(left: Set<T>, right: Set<T>) -> Set<T> { return left.union(right)}
func +(left: Bool, right: Bool) -> Bool { return left || right}
func +<Key, Value>(inout left: Dictionary<Key, Value>, right:Dictionary<Key, Value>) ->
Dictionary<Key, Value> { for (key, value) in right { left.updateValue(value, forKey: key) }}
protocol Concattable { init() func +(left: Self, right: Self) -> Self static func concat(list: [Self]) -> Self}
protocol Concattable { init() static func concat(left: Self, right: Self) -> Self static func concat(list: [Self]) -> Self}
protocol Concattable { func makeEmpty() -> Self func concat(left: Self, right: Self) -> Self func concat(list: [Self]) -> Self}
protocol Concattable { static func empty() -> Self static func append(left: Self, right: Self) -> Self static func concat(list: [Self]) -> Self}
protocol Concattable { static func empty() -> Self static func append(Self, Self) -> Self static func concat([Self]) -> Self}
protocol Concattable { static func empty() -> m static func append(m, m) -> m static func concat([m]) -> m}
protocol Mappable { associatedtype Element func map<OutType>(transform: Element -> OutType) -> Self<OutType>}
protocol Mappable { associatedtype Element static func map<OutType, OutMappable: Mappable where Element == OutType>( transform: (Element -> OutType) ) -> OutMappable}
extension Array: Mappable { func map<OutType>(transform: (Element -> OutType)) -> [OutType] { var result = Array<OutType>() for e in self { result.append(transform(e)) } return result }}
enum Result<ValueType>: Mappable { case Failure(error: ErrorType) case Success(value: ValueType) func map<OutType>(transform: ValueType -> OutType) -> Result<OutType> { switch self { case .Failure(let error): return .Failure(error) case .Success(let value): return .Success(value: transform(value)) } }}
protocol Mappable { associatedtype Element func map<OutType, OutMappable: Mappable where Element == OutType>( transform: (Element -> OutType) ) -> OutMappable}
protocol Mappable { associatedtype Element func map<A, B>(transform: A -> B, input: Self<A>) -> Self<B>}
protocol Mappable { func map(transform: a -> b, input: Self a) -> Self b}
protocol Mappable { func map(a -> b, Self a) -> Self b}
protocol FlatMappable: Mappable { init(element: Element) func flatMap<Out>(transform: Element -> Self<Out>) -> Self<Out>}
protocol FlatMappable: Mappable { init(element: Element) func flatMap<OutType, OutMappable: FlatMappable where Element == OutType>( transform: Element -> OutType) -> OutMappable}
extension Optional: FlatMappable { typealias Element = Wrapped
func flatMap<Out>(transform: Wrapped -> Optional<Out>) -> Optional<Out> { switch self { case .None: return nil case .Some(let value): return transform(value) } }}
Futures e Promises
Future - objeto mantendo um valor que pode estar disponível em algum momento• se o bloco de execução não terminou, dizemos que o Future
ainda não terminou• ao completar a execução, temos um valor ou um erro - Result
FTW
Promise - “extensão” do Future• Pode retornar um Future• Promise pode não completar/executar• read/write
Futures
Future precisa de:
• Contexto de execução• Tarefa a ser executada
class Future<T> { typealias Runnable = () -> Result<T> typealias OnSuccessCallBack = (T) -> () typealias OnFailueCallBack = (NSError) -> () typealias OnComplete = (result: Result<T>) -
//wrapper de dispatch_queue_t > () let extension: ExecutionContext var result: Result<T>? = nil { didSet { self.performCallbacks() } }}
extension Future { func then<U>(executor: ExecutionContext = ExecutionContext.defaultContext, task: (value: T) -> Result<U>) -> Future<U> { let future = Future<U>() self.onComplete() { result in switch result { case .Error(let e): syncronized(future) { future.result = Result<U>(e) } case .Value(let v): future.execute(executor) { return task(value: result.value!) } } } }}
class Promise<T>: Future<T> { func success(v: T) { } func failure(e: NSError) { }}
future { if let cached = self.cachedData() { cached.success(cachedData) } return retriveData(url).flatMap( deserialize($0))}.onSuccess { items in self.updateUI(items) self.cacheItems(items)}
cached.onSuccess { items in self.updateUI(items)}
protocol FlatMappable: Mappable { init(element: Element) func flatMap<Out>(transform: Element -> Self<Out>) -> Self<Out>}
protocol Bindable: Mappable { init(element: Element) func bind<Out>( input: Self<In>, transform: In -> Self<Out>) -> Self<Out>}
protocol FlatMappable: Mappable { func empty() -> m func flatMap(a -> m b) -> m b}
Para fins educacionais
protocol ~> class
protocol Concattable { func empty() -> m func append(m, m) -> m func concat([m]) -> m}
class Monoid m wheremempty :: mmappend :: m -> m -
> mmconcat :: [m] -> m
Ja falamos de
Monoid
protocol Mappable { func map(a -> b, Self a) -> Self b}
class Functor f wherefmap :: (a -> b) -> f a -
> f b
Ja falamos de
MonoidFunctor
protocol FlatMappable: Mappable { func empty() -> m func flatMap(a -> m b) -> m b}
class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
Ja falamos de
MonoidFunctorMonad
De modo simples..
protocol ~> classConcattable ~> MonoidMappable ~> Functor
FlatMappable ~> Monad
A monad is just a monoid in the category of endofunctors, what's the problem?
http://stackoverflow.com/questions/3870088/a-monad-is-just-a-monoid-in-the-category-of-endofunctors-whats-the-issue
Incompleto: piada criada em “A Brief, Incomplete, and Mostly Wrong History of Programming Languages”
Qual o problema?
Então, o que é uma Monad?
All told, a monad in X is just a monoid in the category of endofunctors of X, with product × replaced by composition of endofunctors and unit set by the identity endofunctor.
A monad is just a monoid in the category of endofunctors, what's the problem?
Vs
Então, o que é uma Monad?
Uma forma de criar complexidade, partindo de simplicidade
Monads famosas em Haskell (ainda não implementadas em Swift)
• I/O Monad• State Monad• Reader/Writer Monad• Continuation Monad
Outras coisas que podem ser criadas com monads
• Frameworks reativos• DSL• trabalho com coleções (LINQ)
Outras referências
• Finally Understand Monads with this One Weird Trick by Andy Bartholomew• Monads are Not Monsters by Junior Bontognali• Don’t Fear the Monads by Bryan Beckman• Abstraction, intuition, and the “monad tutorial fallacy” by Brent• Haskell for Mac - App Store
www.concretesolutions.com.brblog.concretesolutions.com.br
Rio de Janeiro – Rua São José, 90 – cj. 2121Centro – (21) 2240-2030
São Paulo - Rua Sansão Alves dos Santos, 433 4º andar - Brooklin - (11) 4119-0449