Successfully reported this slideshow.

Introduction to Functional Reactive Programming

1

Share

Upcoming SlideShare
Code europe
Code europe
Loading in …3
×
1 of 79
1 of 79

Introduction to Functional Reactive Programming

1

Share

Download to read offline

Introduction to functional reactive programming. ReactiveCocoa is used as example FRP inspired framework.

Introduction to functional reactive programming. ReactiveCocoa is used as example FRP inspired framework.

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

Introduction to Functional Reactive Programming

  1. 1. About me Eliasz Sawicki Blog: www.eliaszsawicki.com Twitter: @EliSawic @EliSawic
  2. 2. Introduction to Functional Reactive Programming @EliSawic
  3. 3. Agenda • What is Functional Reactive Programming? • Let's take a look at ReactiveCocoa • Working with streams • Real life example • Conclusion @EliSawic
  4. 4. Functional Reactive Programming @EliSawic
  5. 5. Wikipedia Functional 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
  6. 6. Reactive Programming @EliSawic
  7. 7. Asynchronous Dataflow @EliSawic
  8. 8. Reacting to state changes @EliSawic
  9. 9. Functional Programming @EliSawic
  10. 10. Immutable @EliSawic
  11. 11. assert(f(x) == f(x)) @EliSawic
  12. 12. A person class 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
  13. 13. Mutable let 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") // true makeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // false makeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // false @EliSawic
  14. 14. Immutable let 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") // true makeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // true makeAPhoneCall(device: mobilePhone, person: john, countryCode: "+48") // true @EliSawic
  15. 15. Stateless @EliSawic
  16. 16. Stateful var value = 0 func increment() -> Int { value += 1 return value } @EliSawic
  17. 17. Stateless func increment(value: Int) -> Int { return value + 1 } @EliSawic
  18. 18. Functional Reactive Programming @EliSawic
  19. 19. Imperative vs Declarative @EliSawic
  20. 20. Imperative @EliSawic
  21. 21. Imperative let array = [0, 1, 2, 3, 4, 5] var evenNumbers = [Int]() for element in array { if element % 2 == 0 { evenNumbers.append(element) } } @EliSawic
  22. 22. Declarative @EliSawic
  23. 23. Declarative let array = [0, 1, 2, 3, 4, 5] let evenNumbers = array.filter { $0 % 2 == 0 } @EliSawic
  24. 24. ReactiveCocoa @EliSawic
  25. 25. Event streams @EliSawic
  26. 26. Event Stream @EliSawic
  27. 27. Event @EliSawic
  28. 28. Non-Terminating • Next @EliSawic
  29. 29. Terminating • Completed • Failed • Interrupted (Reactive Cocoa) @EliSawic
  30. 30. Signal @EliSawic
  31. 31. Events over time @EliSawic
  32. 32. No side effects @EliSawic
  33. 33. No random access to events @EliSawic
  34. 34. Must be observed in order to access it's events @EliSawic
  35. 35. Hot @EliSawic
  36. 36. Signal's lifetime • Passes any number of Next events • "Dies" when terminating event • Any new observer will receive Interrupted event @EliSawic
  37. 37. Observing let 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
  38. 38. Pipe @EliSawic
  39. 39. Pipe let (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 test observer.sendCompleted() // Test completed @EliSawic
  40. 40. SignalProducer @EliSawic
  41. 41. Represents tasks @EliSawic
  42. 42. Creates signal @EliSawic
  43. 43. Possible side effects @EliSawic
  44. 44. Does not start it's work if not started @EliSawic
  45. 45. Cold @EliSawic
  46. 46. Using Signal Producer let 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
  47. 47. Cold vs Hot @EliSawic
  48. 48. Properties @EliSawic
  49. 49. MutableProperty let name = MutableProperty("Bob") name.producer.startWithNext { (text) in print(text) } name.value = "Lisa" @EliSawic
  50. 50. Bindings @EliSawic
  51. 51. Basic binding let property = MutableProperty<String>("") let (signal, _) = Signal<String, NoError>.pipe() property <~ signal @EliSawic
  52. 52. Schedulers @EliSawic
  53. 53. Memory Management @EliSawic
  54. 54. Disposables @EliSawic
  55. 55. Manipulating signals @EliSawic
  56. 56. Map @EliSawic
  57. 57. Filter @EliSawic
  58. 58. Aggregating @EliSawic
  59. 59. Skip repeats @EliSawic
  60. 60. Manipulating multiple signals @EliSawic
  61. 61. Combine latest @EliSawic
  62. 62. Zip @EliSawic
  63. 63. Merge @EliSawic
  64. 64. Chaining operators @EliSawic
  65. 65. 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
  66. 66. Example @EliSawic
  67. 67. @EliSawic
  68. 68. @EliSawic
  69. 69. @EliSawic
  70. 70. @EliSawic
  71. 71. @EliSawic
  72. 72. How does it work? @EliSawic
  73. 73. Is name valid? let isValidName = nameSignal.map { (name) -> Bool in return input.characters.count > 2 } @EliSawic
  74. 74. 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
  75. 75. Combine Latest let formData = combineLatest(isValidName, isValidSurname, isValidMail) @EliSawic
  76. 76. Is form valid? disposables += isFormValid <~ formData.map { (isValidName, isValidSurname, isValidMail) -> Bool in return isValidMail && isValidSurname && isValidMail } @EliSawic
  77. 77. Button state let producer = isFormValid.producer.skipRepeats() disposables += producer.startWithNext {[unowned self] (isValid) in self.updateAcceptButtonWithState(isValid) } @EliSawic
  78. 78. Conclusion @EliSawic
  79. 79. Thank you for your attention! @EliSawic

×