introduction to functional reactive programming
TRANSCRIPT
![Page 1: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/1.jpg)
About me
Eliasz SawickiBlog: www.eliaszsawicki.comTwitter: @EliSawic
@EliSawic
![Page 2: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/2.jpg)
Introduction to Functional Reactive
Programming
@EliSawic
![Page 3: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/3.jpg)
Agenda• What is Functional Reactive Programming?
• Let's take a look at ReactiveCocoa
• Working with streams
• Real life example
• Conclusion
@EliSawic
![Page 4: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/4.jpg)
Functional Reactive Programming
@EliSawic
![Page 5: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/5.jpg)
WikipediaFunctional reactive programming (FRP) is a programming paradigm for reactive programming (asynchronous dataflow programming) using the building blocks of functional programming (e.g. map, reduce, filter).
@EliSawic
![Page 6: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/6.jpg)
Reactive Programming
@EliSawic
![Page 7: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/7.jpg)
Asynchronous Dataflow
@EliSawic
![Page 8: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/8.jpg)
Reacting to state changes
@EliSawic
![Page 9: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/9.jpg)
Functional Programming
@EliSawic
![Page 10: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/10.jpg)
Immutable
@EliSawic
![Page 11: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/11.jpg)
assert(f(x) == f(x))
@EliSawic
![Page 12: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/12.jpg)
A personclass Person { let name: String let phoneNumber: String init(name: String, phoneNumber: String) { self.name = name self.phoneNumber = phoneNumber }}
class MobilePhone { func call(person: Person) -> Bool { // implementation }}
@EliSawic
![Page 13: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/13.jpg)
Mutablelet mobilePhone = MobilePhone()let john = Person(name: "John", phoneNumber: "123456789")
func makeAPhoneCall(device: Phone, person: Person, countryCode: String) -> Bool { person.phoneNumber = countryCode + person.phoneNumber let success = device.call(person) return success}
makeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // truemakeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // falsemakeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // false
@EliSawic
![Page 14: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/14.jpg)
Immutablelet mobilePhone = MobilePhone()let john = Person(name: "John", phoneNumber: "123456789")
func makeAPhoneCall(device: Phone, person: Person, countryCode: String) -> Bool { let prefixedPhoneNumber = countryCode + person.phoneNumber let newPerson = Person(name: person.name, phoneNumber: prefixedPhoneNumber) let success = device.call(newPerson) return success}
makeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // truemakeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // truemakeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // true
@EliSawic
![Page 15: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/15.jpg)
Stateless
@EliSawic
![Page 16: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/16.jpg)
Statefulvar value = 0
func increment() -> Int { value += 1 return value}
@EliSawic
![Page 17: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/17.jpg)
Statelessfunc increment(value: Int) -> Int { return value + 1}
@EliSawic
![Page 18: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/18.jpg)
Functional Reactive Programming
@EliSawic
![Page 19: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/19.jpg)
Imperative vs
Declarative
@EliSawic
![Page 20: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/20.jpg)
Imperative
@EliSawic
![Page 21: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/21.jpg)
Imperativelet array = [0, 1, 2, 3, 4, 5]var evenNumbers = [Int]()for element in array { if element % 2 == 0 { evenNumbers.append(element) }}
@EliSawic
![Page 22: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/22.jpg)
Declarative
@EliSawic
![Page 23: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/23.jpg)
Declarativelet array = [0, 1, 2, 3, 4, 5]let evenNumbers = array.filter { $0 % 2 == 0 }
@EliSawic
![Page 24: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/24.jpg)
ReactiveCocoa
@EliSawic
![Page 25: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/25.jpg)
Event streams
@EliSawic
![Page 26: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/26.jpg)
Event Stream
@EliSawic
![Page 27: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/27.jpg)
Event
@EliSawic
![Page 28: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/28.jpg)
Non-Terminating• Next
@EliSawic
![Page 29: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/29.jpg)
Terminating
• Completed
• Failed
• Interrupted (Reactive Cocoa)
@EliSawic
![Page 30: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/30.jpg)
Signal
@EliSawic
![Page 31: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/31.jpg)
Events over time
@EliSawic
![Page 32: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/32.jpg)
No side effects
@EliSawic
![Page 33: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/33.jpg)
No random access to events
@EliSawic
![Page 34: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/34.jpg)
Must be observed in order to access it's
events
@EliSawic
![Page 35: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/35.jpg)
Hot
@EliSawic
![Page 36: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/36.jpg)
Signal's lifetime• Passes any number of Next events
• "Dies" when terminating event
• Any new observer will receive Interrupted event
@EliSawic
![Page 37: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/37.jpg)
Observinglet someWork = Signal<Int, NoError> { observer in observer.sendNext(1) observer.sendNext(2) .... observer.sendNext(1000000) observer.sendCompleted()}
signal.observe { (event) in print(event)}signal.observeNext { (value) in print(value)}
signal.observeCompleted { print("Completed")}
@EliSawic
![Page 38: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/38.jpg)
Pipe
@EliSawic
![Page 39: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/39.jpg)
Pipelet (signal, observer) = Signal<String, NoError>.pipe()
signal.observeNext({ text in print(text)})
signal.observeCompleted({ print("Test completed")})
observer.sendNext("It's a test") // It's a testobserver.sendCompleted() // Test completed
@EliSawic
![Page 40: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/40.jpg)
SignalProducer
@EliSawic
![Page 41: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/41.jpg)
Represents tasks
@EliSawic
![Page 42: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/42.jpg)
Creates signal
@EliSawic
![Page 43: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/43.jpg)
Possible side effects
@EliSawic
![Page 44: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/44.jpg)
Does not start it's work if not started
@EliSawic
![Page 45: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/45.jpg)
Cold
@EliSawic
![Page 46: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/46.jpg)
Using Signal Producerlet producer = SignalProducer<String, NSError> { (observer, composite) in observer.sendNext("In Progress...") // ...... observer.sendCompleted()}
producer.startWithSignal { (signal, _) in signal.observeNext({ (text) in print(text) // In Progress... }) signal.observeCompleted({ print("Test completed") // Test completed })}
@EliSawic
![Page 47: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/47.jpg)
Cold vs Hot
@EliSawic
![Page 48: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/48.jpg)
Properties
@EliSawic
![Page 49: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/49.jpg)
MutablePropertylet name = MutableProperty("Bob")
name.producer.startWithNext { (text) in print(text)}
name.value = "Lisa"
@EliSawic
![Page 50: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/50.jpg)
Bindings
@EliSawic
![Page 51: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/51.jpg)
Basic bindinglet property = MutableProperty<String>("")let (signal, _) = Signal<String, NoError>.pipe()property <~ signal
@EliSawic
![Page 52: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/52.jpg)
Schedulers
@EliSawic
![Page 53: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/53.jpg)
Memory Management
@EliSawic
![Page 54: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/54.jpg)
Disposables
@EliSawic
![Page 55: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/55.jpg)
Manipulating signals
@EliSawic
![Page 56: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/56.jpg)
Map
@EliSawic
![Page 57: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/57.jpg)
Filter
@EliSawic
![Page 58: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/58.jpg)
Aggregating
@EliSawic
![Page 59: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/59.jpg)
Skip repeats
@EliSawic
![Page 60: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/60.jpg)
Manipulating multiple signals
@EliSawic
![Page 61: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/61.jpg)
Combine latest
@EliSawic
![Page 62: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/62.jpg)
Zip
@EliSawic
![Page 63: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/63.jpg)
Merge
@EliSawic
![Page 64: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/64.jpg)
Chaining operators
@EliSawic
![Page 65: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/65.jpg)
Chain them all!let newSignalX = signalX.skipRepeats() .filter { x > 2 } .map { x * 10 }
let newSignalY = signalY.filter { x > 10 }
let combined = combineLatest(newSignalX, newSignalY)
combined.observeNext { xValue, yValue in print("Update: \(xValue) : \(yValue)")}
@EliSawic
![Page 66: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/66.jpg)
Example
@EliSawic
![Page 67: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/67.jpg)
@EliSawic
![Page 68: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/68.jpg)
@EliSawic
![Page 69: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/69.jpg)
@EliSawic
![Page 70: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/70.jpg)
@EliSawic
![Page 71: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/71.jpg)
@EliSawic
![Page 72: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/72.jpg)
How does it work?
@EliSawic
![Page 73: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/73.jpg)
Is name valid?let isValidName = nameSignal.map { (name) -> Bool in return input.characters.count > 2}
@EliSawic
![Page 74: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/74.jpg)
Is mail valid?let isValidMail = mailSignal.map { (mail) -> Bool in let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}" let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx) return emailTest.evaluateWithObject(mail)}
@EliSawic
![Page 75: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/75.jpg)
Combine Latestlet formData = combineLatest(isValidName, isValidSurname, isValidMail)
@EliSawic
![Page 76: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/76.jpg)
Is form valid?disposables += isFormValid <~ formData.map { (isValidName, isValidSurname, isValidMail) -> Bool in return isValidMail && isValidSurname && isValidMail}
@EliSawic
![Page 77: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/77.jpg)
Button statelet producer = isFormValid.producer.skipRepeats()disposables += producer.startWithNext {[unowned self] (isValid) in self.updateAcceptButtonWithState(isValid)}
@EliSawic
![Page 78: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/78.jpg)
Conclusion
@EliSawic
![Page 79: Introduction to Functional Reactive Programming](https://reader030.vdocuments.us/reader030/viewer/2022021506/58729eda1a28ab07208b54c7/html5/thumbnails/79.jpg)
Thank you for your attention!
@EliSawic