SlideShare a Scribd company logo
Programação Funcional na
Prática com Swift
Rodrigo Amorim Ruiz
Vikki (vikki.ai)
Porque Swift
• Passagem por valor
• Tipagem estática + inferência
• Optional
• Lambda e outras construções de FP
• Enum
VS
Programação Orientada a Objetos
Programação Funcional
Comparação
Considerações
• Swift vs Cocoa
• Questão de estilo
• OO / Procedural / Imperativo
• Técnicas de FP em OO
• Performance
• Leitura vs Escrita
• Melhor ferramenta para cada problema
Programação Funcional Programação Orientada a ObjetosVS
Programação Funcional Programação Orientada a ObjetosVS
TDC2018SP | Trilha Prog Funcional - Programacao funcional na pratica com Swift
Motivos
TDC2018SP | Trilha Prog Funcional - Programacao funcional na pratica com Swift
Class vs Struct
// OO
func customPrint(person: Person) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(10), execute: {
print("After 10 seconds: (person.name)")
})
}
class Person {
var name: String
init(name: String) {
self.name = name
}
}
let p = Person(name: "Rodrigo")
customPrint(person: p)
p.name = "Thomas"
print(p.name)
Class vs Struct
// FP
func customPrint(person: Person) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(10), execute: {
print("After 10 seconds: (person.name)")
})
}
struct Person {
var name: String
}
let p = Person(name: "Rodrigo")
customPrint(person: p)
p.name = "Thomas"
print(p.name)
Map
// OO
var values = [Double]()
for step in steps {
values.append(sin(Double(step) / 10))
}
print(values)
// FP
let values = steps.map({ sin(Double($0) / 10) })
print(values)
let steps = (1...100)
Filter
// OO
var partyFriends = [String]()
for friend in friends {
if friend.age >= 18 && friend.age <= 40 {
partyFriends.append(friend.name)
}
}
print(partyFriends)
// FP
let partyFriends = friends
.filter({ $0.age >= 18 && $0.age <= 40 })
.map({ $0.name })
print(partyFriends)
let friends = [
(name: "Pedro", age: 12),
(name: "Maria", age: 18),
(name: "João", age: 21),
(name: "Regina", age: 55)
]
Reduce
// OO
var totalMoney = 0
for money in moneyPile {
totalMoney += money
}
var text = ""
for character in characters {
text += character
}
print(totalMoney)
print(text)
// FP
let totalMoney = moneyPile.reduce(0, +)
let text = characters.reduce("", +)
print(totalMoney)
print(text)
let moneyPile = [10, 20, 15, 30]
let characters = ["a", "b", "c", "d"]
Count Words
// Procedural
let content = readFile()
let words = content.split(separator: " ")
var tally = [String: Int]()
for word in words {
let lowerCaseWord = word.lowercased()
tally[lowerCaseWord] = (tally[lowerCaseWord] ?? 0) + 1
}
var tallyAsArray = [(word: String, count: Int)]()
for (key, value) in tally {
tallyAsArray.append((word: key, count: value))
}
tallyAsArray.sort(by: { $0.count > $1.count })
var top10 = [(word: String, count: Int)]()
for i in (0..<10) {
top10.append(tallyAsArray[i])
}
for value in top10 {
print("(value.word) - (value.count)")
}
Count Words
// OO
class WordCounter {
func printTop10() {
readFileToContent()
splitContentIntoWords()
createTally()
sortTally()
getTop10Words()
printTop10()
}
private var content = ""
private var words = [String.SubSequence]()
private var tally = [String: Int]()
private var tallyAsArray = [(word: String, count: Int)]()
private var top10 = [(word: String, count: Int)]()
private func readFileToContent() { … }
private func splitContentIntoWords() { … }
private func createTally() { … }
private func sortTally() { … }
private func getTop10Words() { … }
private func printTop10Words() { … }
}
let w = WordCounter()
w.printTop10()
Count Words
// FP
let output = readFile()
.split(separator: " ")
.map({ $0.lowercased() })
.reduce([String: Int](), { (tally, lowerCaseWord) in
return tally.merging(
[lowerCaseWord: (tally[lowerCaseWord] ?? 0) + 1],
uniquingKeysWith: { $1 }
)
})
.sorted(by: { $0.value > $1.value })
.prefix(10)
.map({ "($0.key) - ($0.value)" })
.joined(separator: "n")
print(output)
Requests (OO)
let party = CreateParty(delegate: CreatePartyDelegate())
party.create()
class CreateParty: SendAPIRequestDelegate {
init(delegate: CreatePartyDelegate) {
self.delegate = delegate
self.friendsRequest = SendAPIRequest(url: "https://api.com/friends", delegate: self)
self.placeRequest = SendAPIRequest(url: "https://api.com/place", delegate: self)
}
func create() {
self.friendsRequest.request()
self.placeRequest.request()
}
...
}
Requests (OO)
class CreateParty: SendAPIRequestDelegate {
...
// MARK: - SendAPIRequestDelegate
func success(request: SendAPIRequest, json: JSON) {
if request === self.friendsRequest {
self.friends = json.array!.map(toString)
friendsReady = true
tryToCreatePartyData()
}
if request === self.placeRequest {
self.place = json.string!
placeReady = true
tryToCreatePartyData()
}
}
func failure(request: SendAPIRequest, error: APIRequestError) {
if request === self.friendsRequest {
friendsReady = true
tryToCreatePartyData()
}
if request === self.placeRequest {
placeReady = true
tryToCreatePartyData()
}
}
...
}
Requests (OO)
class CreateParty: SendAPIRequestDelegate {
...
// MARK: - Private
private var friendsRequest: SendAPIRequest!
private var placeRequest: SendAPIRequest!
private var friendsReady = false
private var placeReady = false
private var friends: [String]?
private var place: String?
private let delegate: CreatePartyDelegate
private var party: Party?
private func tryToCreatePartyData() {
if !self.friendsReady || !self.placeReady {
return
}
if let friends = self.friends, let place = self.place {
self.party = Party(friends: friends, place: place)
} else {
self.party = nil
}
callDelegateWithPartyData()
}
...
}
Requests (OO)
class CreatePartyDelegate {
func printNoParty() {
print("There will be no party.")
}
func printParty(party: Party) {
print("Go party!!!")
print("Place: (party.place)")
print("Friends:")
for friend in party.friends {
print(friend)
}
}
}
class CreateParty: SendAPIRequestDelegate {
...
// MARK: - Private
...
private func callDelegateWithPartyData() {
guard let party = self.party else {
delegate.printNoParty()
return
}
delegate.printParty(party: party)
}
}
Requests (FP1)
let friendsObservable = sendAPIRequest(url: "https://api.com/friends")
.map(getSuccess >>> map(toArray >>> map(toString)))
let placeObservable = sendAPIRequest(url: "https://api.com/place")
.map(getSuccess >>> map(toString))
let partyObservable = Observable
.zip(friendsObservable, placeObservable)
.map(mergeOptionals >>> map(applyTuple(Party.init)))
let outputObservable = partyObservable.map(
map({
"Go party!!!n"
+ "Place: ($0.place)n"
+ "Friends:n"
+ $0.friends.joined(separator: "n")
})
>>> defaultTo("There will be no party.")
)
_ = outputObservable.subscribe(onNext: { print($0) })
Requests (FP2)
(
"https://api.com/friends",
"https://api.com/place"
)
>>> both(sendAPIRequest >>> map(getSuccess))
>>> first(map(map(toArray >>> map(toString))))
>>> second(map(map(toString)))
>>> applyTuple(Observable.zip)
>>> map(mergeOptionals >>> map(applyTuple(Party.init)))
>>> map(
map({
"Go party!!!n"
+ "Place: ($0.place)n"
+ "Friends:n"
+ $0.friends.joined(separator: "n")
})
>>> defaultTo("There will be no party.")
)
>>> subscribe(onNext: { print($0) })
Requests (FP2’)
let mapFriends: (Observable<JSON?>) -> Observable<[String]?> = map(map(toArray >>> map(toString)))
let mapPlace: (Observable<JSON?>) -> Observable<String?> = map(map(toString))
let requests = both(sendAPIRequest >>> map(getSuccess))
>>> first(mapFriends)
>>> second(mapPlace)
let createParty: ((Observable<[String]?>, Observable<String?>)) -> Observable<Party?> =
applyTuple(Observable.zip)
>>> map(mergeOptionals >>> map(applyTuple(Party.init)))
let toOutputString: (Observable<Party?>) -> Observable<String> = map(
map({
"Go party!!!n"
+ "Place: ($0.place)n"
+ "Friends:n"
+ $0.friends.joined(separator: "n")
})
>>> defaultTo("There will be no party.")
)
let requestStringsToOutput = requests
>>> createParty
>>> toOutputString
_ = requestStringsToOutput((
"https://api.com/friends",
"https://api.com/place"
)).subscribe(onNext: { print($0) })
AI
Conceitos Utilizados
• Dados x Comportamento
• Imperativo vs Declarativo
• Funções puras
• Imutabilidade
• Funções de alta ordem
• Functors, Applicatives e Monads
• Maybe (Optional)
• Array
• Result
• Promise / Observable
Haskell vs. Ada vs. C++ vs. Awk vs. ...
An Experiment in Software Prototyping
Productivity∗
Paul Hudak Mark P. Jones
Yale University
Department of Computer Science
New Haven, CT 06518 {hudak-paul,jones-mark}@cs.yale.edu
July 4, 1994
https://www.linkedin.com/in/rodrigoaruiz/

More Related Content

KEY
CS442 - Rogue: A Scala DSL for MongoDB
PDF
Postgre(No)SQL - A JSON journey
ODP
Php 102: Out with the Bad, In with the Good
PDF
Kotlin Basics - Apalon Kotlin Sprint Part 2
PDF
Leveraging the Power of Graph Databases in PHP
PDF
Leveraging the Power of Graph Databases in PHP
KEY
Scala Days 2011 - Rogue: A Type-Safe DSL for MongoDB
PPT
CS442 - Rogue: A Scala DSL for MongoDB
Postgre(No)SQL - A JSON journey
Php 102: Out with the Bad, In with the Good
Kotlin Basics - Apalon Kotlin Sprint Part 2
Leveraging the Power of Graph Databases in PHP
Leveraging the Power of Graph Databases in PHP
Scala Days 2011 - Rogue: A Type-Safe DSL for MongoDB

What's hot (15)

KEY
Java Fx Tutorial01
PPTX
Working With JQuery Part1
PDF
Introduzione JQuery
PDF
Ruby Language - A quick tour
PDF
Groovy scripts with Groovy
PPTX
Looping the Loop with SPL Iterators
PDF
HTML5 and CSS3 Refresher
PDF
The Ring programming language version 1.2 book - Part 19 of 84
PDF
The Ring programming language version 1.2 book - Part 33 of 84
KEY
Metaprogramming in Haskell
PPT
Groovy unleashed
PPT
An Elephant of a Different Colour: Hack
PDF
Ruby - Design patterns tdc2011
PDF
Assiciate Expressions to Names in Scala
PPTX
TRICK
Java Fx Tutorial01
Working With JQuery Part1
Introduzione JQuery
Ruby Language - A quick tour
Groovy scripts with Groovy
Looping the Loop with SPL Iterators
HTML5 and CSS3 Refresher
The Ring programming language version 1.2 book - Part 19 of 84
The Ring programming language version 1.2 book - Part 33 of 84
Metaprogramming in Haskell
Groovy unleashed
An Elephant of a Different Colour: Hack
Ruby - Design patterns tdc2011
Assiciate Expressions to Names in Scala
TRICK
Ad

Similar to TDC2018SP | Trilha Prog Funcional - Programacao funcional na pratica com Swift (20)

PDF
WTF Oriented Programming, com Fabio Akita
PDF
Swift School #1
PDF
Postobjektové programovanie v Ruby
PDF
Scala: Functioneel programmeren in een object georiënteerde wereld
PDF
PDF
Apache spark: in and out
PDF
python codes
KEY
CoffeeScript - A Rubyist's Love Affair
PPTX
Scala best practices
KEY
あたかも自然言語を書くようにコーディングしてみる
PDF
Patterns in Terraform 12+13: Data, Transformations and Resources
PDF
Generics and Inference
PDF
Python
PDF
Ejercicios de estilo en la programación
PPTX
Building a friendly .NET SDK to connect to Space
PDF
[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark Applications
PPTX
Testing batch and streaming Spark applications
PDF
SWP - A Generic Language Parser
PPTX
The Workflow Pattern, Composed (2021)
PDF
From android/java to swift (3)
WTF Oriented Programming, com Fabio Akita
Swift School #1
Postobjektové programovanie v Ruby
Scala: Functioneel programmeren in een object georiënteerde wereld
Apache spark: in and out
python codes
CoffeeScript - A Rubyist's Love Affair
Scala best practices
あたかも自然言語を書くようにコーディングしてみる
Patterns in Terraform 12+13: Data, Transformations and Resources
Generics and Inference
Python
Ejercicios de estilo en la programación
Building a friendly .NET SDK to connect to Space
[QE 2018] Łukasz Gawron – Testing Batch and Streaming Spark Applications
Testing batch and streaming Spark applications
SWP - A Generic Language Parser
The Workflow Pattern, Composed (2021)
From android/java to swift (3)
Ad

More from tdc-globalcode (20)

PDF
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
PDF
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
PDF
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
PDF
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
PDF
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
PDF
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
PDF
TDC2019 Intel Software Day - Inferencia de IA em edge devices
PDF
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
PPT
Trilha .Net - Programacao funcional usando f#
PDF
TDC2018SP | Trilha Go - Case Easylocus
PDF
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
PDF
TDC2018SP | Trilha Go - Clean architecture em Golang
PDF
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
PDF
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
PDF
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
PDF
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
PDF
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
PDF
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
PDF
TDC2018SP | Trilha .Net - .NET funcional com F#
PDF
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core
TDC2019 Intel Software Day - Visao Computacional e IA a servico da humanidade
TDC2019 Intel Software Day - Tecnicas de Programacao Paralela em Machine Lear...
TDC2019 Intel Software Day - ACATE - Cases de Sucesso
TDC2019 Intel Software Day - Otimizacao grafica com o Intel GPA
TDC2019 Intel Software Day - Deteccao de objetos em tempo real com OpenVino
TDC2019 Intel Software Day - OpenCV: Inteligencia artificial e Visao Computac...
TDC2019 Intel Software Day - Inferencia de IA em edge devices
Trilha BigData - Banco de Dados Orientado a Grafos na Seguranca Publica
Trilha .Net - Programacao funcional usando f#
TDC2018SP | Trilha Go - Case Easylocus
TDC2018SP | Trilha Modern Web - Para onde caminha a Web?
TDC2018SP | Trilha Go - Clean architecture em Golang
TDC2018SP | Trilha Go - "Go" tambem e linguagem de QA
TDC2018SP | Trilha Mobile - Digital Wallets - Seguranca, inovacao e tendencia
TDC2018SP | Trilha .Net - Real Time apps com Azure SignalR Service
TDC2018SP | Trilha .Net - Passado, Presente e Futuro do .NET
TDC2018SP | Trilha .Net - Novidades do C# 7 e 8
TDC2018SP | Trilha .Net - Obtendo metricas com TDD utilizando build automatiz...
TDC2018SP | Trilha .Net - .NET funcional com F#
TDC2018SP | Trilha .Net - Crie SPAs com Razor e C# usando Blazor em .Net Core

Recently uploaded (20)

PDF
Trump Administration's workforce development strategy
PDF
Paper A Mock Exam 9_ Attempt review.pdf.
PPTX
History, Philosophy and sociology of education (1).pptx
PPTX
Introduction to pro and eukaryotes and differences.pptx
PPTX
B.Sc. DS Unit 2 Software Engineering.pptx
PDF
David L Page_DCI Research Study Journey_how Methodology can inform one's prac...
PDF
Practical Manual AGRO-233 Principles and Practices of Natural Farming
PPTX
202450812 BayCHI UCSC-SV 20250812 v17.pptx
PDF
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
DOC
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
PDF
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 1)
PPTX
Chinmaya Tiranga Azadi Quiz (Class 7-8 )
PDF
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
PDF
Vision Prelims GS PYQ Analysis 2011-2022 www.upscpdf.com.pdf
PDF
1_English_Language_Set_2.pdf probationary
PDF
Τίμαιος είναι φιλοσοφικός διάλογος του Πλάτωνα
PDF
A GUIDE TO GENETICS FOR UNDERGRADUATE MEDICAL STUDENTS
PPTX
ELIAS-SEZIURE AND EPilepsy semmioan session.pptx
PDF
IGGE1 Understanding the Self1234567891011
PDF
Indian roads congress 037 - 2012 Flexible pavement
Trump Administration's workforce development strategy
Paper A Mock Exam 9_ Attempt review.pdf.
History, Philosophy and sociology of education (1).pptx
Introduction to pro and eukaryotes and differences.pptx
B.Sc. DS Unit 2 Software Engineering.pptx
David L Page_DCI Research Study Journey_how Methodology can inform one's prac...
Practical Manual AGRO-233 Principles and Practices of Natural Farming
202450812 BayCHI UCSC-SV 20250812 v17.pptx
Black Hat USA 2025 - Micro ICS Summit - ICS/OT Threat Landscape
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 1)
Chinmaya Tiranga Azadi Quiz (Class 7-8 )
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
Vision Prelims GS PYQ Analysis 2011-2022 www.upscpdf.com.pdf
1_English_Language_Set_2.pdf probationary
Τίμαιος είναι φιλοσοφικός διάλογος του Πλάτωνα
A GUIDE TO GENETICS FOR UNDERGRADUATE MEDICAL STUDENTS
ELIAS-SEZIURE AND EPilepsy semmioan session.pptx
IGGE1 Understanding the Self1234567891011
Indian roads congress 037 - 2012 Flexible pavement

TDC2018SP | Trilha Prog Funcional - Programacao funcional na pratica com Swift

  • 1. Programação Funcional na Prática com Swift Rodrigo Amorim Ruiz Vikki (vikki.ai)
  • 2. Porque Swift • Passagem por valor • Tipagem estática + inferência • Optional • Lambda e outras construções de FP • Enum
  • 3. VS Programação Orientada a Objetos Programação Funcional Comparação
  • 4. Considerações • Swift vs Cocoa • Questão de estilo • OO / Procedural / Imperativo • Técnicas de FP em OO • Performance • Leitura vs Escrita • Melhor ferramenta para cada problema
  • 10. Class vs Struct // OO func customPrint(person: Person) { DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(10), execute: { print("After 10 seconds: (person.name)") }) } class Person { var name: String init(name: String) { self.name = name } } let p = Person(name: "Rodrigo") customPrint(person: p) p.name = "Thomas" print(p.name)
  • 11. Class vs Struct // FP func customPrint(person: Person) { DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(10), execute: { print("After 10 seconds: (person.name)") }) } struct Person { var name: String } let p = Person(name: "Rodrigo") customPrint(person: p) p.name = "Thomas" print(p.name)
  • 12. Map // OO var values = [Double]() for step in steps { values.append(sin(Double(step) / 10)) } print(values) // FP let values = steps.map({ sin(Double($0) / 10) }) print(values) let steps = (1...100)
  • 13. Filter // OO var partyFriends = [String]() for friend in friends { if friend.age >= 18 && friend.age <= 40 { partyFriends.append(friend.name) } } print(partyFriends) // FP let partyFriends = friends .filter({ $0.age >= 18 && $0.age <= 40 }) .map({ $0.name }) print(partyFriends) let friends = [ (name: "Pedro", age: 12), (name: "Maria", age: 18), (name: "João", age: 21), (name: "Regina", age: 55) ]
  • 14. Reduce // OO var totalMoney = 0 for money in moneyPile { totalMoney += money } var text = "" for character in characters { text += character } print(totalMoney) print(text) // FP let totalMoney = moneyPile.reduce(0, +) let text = characters.reduce("", +) print(totalMoney) print(text) let moneyPile = [10, 20, 15, 30] let characters = ["a", "b", "c", "d"]
  • 15. Count Words // Procedural let content = readFile() let words = content.split(separator: " ") var tally = [String: Int]() for word in words { let lowerCaseWord = word.lowercased() tally[lowerCaseWord] = (tally[lowerCaseWord] ?? 0) + 1 } var tallyAsArray = [(word: String, count: Int)]() for (key, value) in tally { tallyAsArray.append((word: key, count: value)) } tallyAsArray.sort(by: { $0.count > $1.count }) var top10 = [(word: String, count: Int)]() for i in (0..<10) { top10.append(tallyAsArray[i]) } for value in top10 { print("(value.word) - (value.count)") }
  • 16. Count Words // OO class WordCounter { func printTop10() { readFileToContent() splitContentIntoWords() createTally() sortTally() getTop10Words() printTop10() } private var content = "" private var words = [String.SubSequence]() private var tally = [String: Int]() private var tallyAsArray = [(word: String, count: Int)]() private var top10 = [(word: String, count: Int)]() private func readFileToContent() { … } private func splitContentIntoWords() { … } private func createTally() { … } private func sortTally() { … } private func getTop10Words() { … } private func printTop10Words() { … } } let w = WordCounter() w.printTop10()
  • 17. Count Words // FP let output = readFile() .split(separator: " ") .map({ $0.lowercased() }) .reduce([String: Int](), { (tally, lowerCaseWord) in return tally.merging( [lowerCaseWord: (tally[lowerCaseWord] ?? 0) + 1], uniquingKeysWith: { $1 } ) }) .sorted(by: { $0.value > $1.value }) .prefix(10) .map({ "($0.key) - ($0.value)" }) .joined(separator: "n") print(output)
  • 18. Requests (OO) let party = CreateParty(delegate: CreatePartyDelegate()) party.create() class CreateParty: SendAPIRequestDelegate { init(delegate: CreatePartyDelegate) { self.delegate = delegate self.friendsRequest = SendAPIRequest(url: "https://api.com/friends", delegate: self) self.placeRequest = SendAPIRequest(url: "https://api.com/place", delegate: self) } func create() { self.friendsRequest.request() self.placeRequest.request() } ... }
  • 19. Requests (OO) class CreateParty: SendAPIRequestDelegate { ... // MARK: - SendAPIRequestDelegate func success(request: SendAPIRequest, json: JSON) { if request === self.friendsRequest { self.friends = json.array!.map(toString) friendsReady = true tryToCreatePartyData() } if request === self.placeRequest { self.place = json.string! placeReady = true tryToCreatePartyData() } } func failure(request: SendAPIRequest, error: APIRequestError) { if request === self.friendsRequest { friendsReady = true tryToCreatePartyData() } if request === self.placeRequest { placeReady = true tryToCreatePartyData() } } ... }
  • 20. Requests (OO) class CreateParty: SendAPIRequestDelegate { ... // MARK: - Private private var friendsRequest: SendAPIRequest! private var placeRequest: SendAPIRequest! private var friendsReady = false private var placeReady = false private var friends: [String]? private var place: String? private let delegate: CreatePartyDelegate private var party: Party? private func tryToCreatePartyData() { if !self.friendsReady || !self.placeReady { return } if let friends = self.friends, let place = self.place { self.party = Party(friends: friends, place: place) } else { self.party = nil } callDelegateWithPartyData() } ... }
  • 21. Requests (OO) class CreatePartyDelegate { func printNoParty() { print("There will be no party.") } func printParty(party: Party) { print("Go party!!!") print("Place: (party.place)") print("Friends:") for friend in party.friends { print(friend) } } } class CreateParty: SendAPIRequestDelegate { ... // MARK: - Private ... private func callDelegateWithPartyData() { guard let party = self.party else { delegate.printNoParty() return } delegate.printParty(party: party) } }
  • 22. Requests (FP1) let friendsObservable = sendAPIRequest(url: "https://api.com/friends") .map(getSuccess >>> map(toArray >>> map(toString))) let placeObservable = sendAPIRequest(url: "https://api.com/place") .map(getSuccess >>> map(toString)) let partyObservable = Observable .zip(friendsObservable, placeObservable) .map(mergeOptionals >>> map(applyTuple(Party.init))) let outputObservable = partyObservable.map( map({ "Go party!!!n" + "Place: ($0.place)n" + "Friends:n" + $0.friends.joined(separator: "n") }) >>> defaultTo("There will be no party.") ) _ = outputObservable.subscribe(onNext: { print($0) })
  • 23. Requests (FP2) ( "https://api.com/friends", "https://api.com/place" ) >>> both(sendAPIRequest >>> map(getSuccess)) >>> first(map(map(toArray >>> map(toString)))) >>> second(map(map(toString))) >>> applyTuple(Observable.zip) >>> map(mergeOptionals >>> map(applyTuple(Party.init))) >>> map( map({ "Go party!!!n" + "Place: ($0.place)n" + "Friends:n" + $0.friends.joined(separator: "n") }) >>> defaultTo("There will be no party.") ) >>> subscribe(onNext: { print($0) })
  • 24. Requests (FP2’) let mapFriends: (Observable<JSON?>) -> Observable<[String]?> = map(map(toArray >>> map(toString))) let mapPlace: (Observable<JSON?>) -> Observable<String?> = map(map(toString)) let requests = both(sendAPIRequest >>> map(getSuccess)) >>> first(mapFriends) >>> second(mapPlace) let createParty: ((Observable<[String]?>, Observable<String?>)) -> Observable<Party?> = applyTuple(Observable.zip) >>> map(mergeOptionals >>> map(applyTuple(Party.init))) let toOutputString: (Observable<Party?>) -> Observable<String> = map( map({ "Go party!!!n" + "Place: ($0.place)n" + "Friends:n" + $0.friends.joined(separator: "n") }) >>> defaultTo("There will be no party.") ) let requestStringsToOutput = requests >>> createParty >>> toOutputString _ = requestStringsToOutput(( "https://api.com/friends", "https://api.com/place" )).subscribe(onNext: { print($0) })
  • 25. AI
  • 26. Conceitos Utilizados • Dados x Comportamento • Imperativo vs Declarativo • Funções puras • Imutabilidade • Funções de alta ordem • Functors, Applicatives e Monads • Maybe (Optional) • Array • Result • Promise / Observable
  • 27. Haskell vs. Ada vs. C++ vs. Awk vs. ... An Experiment in Software Prototyping Productivity∗ Paul Hudak Mark P. Jones Yale University Department of Computer Science New Haven, CT 06518 {hudak-paul,jones-mark}@cs.yale.edu July 4, 1994