Code europe

Post on 16-Apr-2017

187 views 0 download

Transcript of Code europe

Introduction to Functional Reactive

Programming

@EliSawic

About me

Eliasz SawickiBlog: www.eliaszsawicki.comTwitter: @EliSawic

@EliSawic

Agenda• What is functional reactive programming?

• Working with streams

• ReactiveSwift - Thinking in signals

• Example

@EliSawic

Functional Reactive Programming

@EliSawic

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

Reactive Programming

@EliSawic

Functional Programming

@EliSawic

Blocks

@EliSawic

Imperative vs

Declarative

@EliSawic

Imperative

@EliSawic

Imperativelet array = [0, 1, 2, 3, 4, 5]var evenNumbers = [Int]()for element in array { if element % 2 == 0 { evenNumbers.append(element) }}

@EliSawic

Declarative

@EliSawic

Declarativelet array = [0, 1, 2, 3, 4, 5]let evenNumbers = array.filter { $0 % 2 == 0 }

@EliSawic

Working with streams

@EliSawic

Stream

@EliSawic

Manipulating streams

@EliSawic

Map

@EliSawic

Filter

@EliSawic

Aggregating

@EliSawic

Manipulating multiple streams

@EliSawic

Combine latest

@EliSawic

Merge

@EliSawic

Chaining streams

@EliSawic

www.rxmarbles.com

@EliSawic

ReactiveSwift

@EliSawic

Thinking in Signals

@EliSawic

What is a signal?

@EliSawic

This screen is a signal

@EliSawic

Represents events over time

@EliSawic

Observing does not trigger side effects

@EliSawic

No random access to events

@EliSawic

Observe

@EliSawic

If you don't listen, it's gone

@EliSawic

What is event?

@EliSawic

Eventstruct Idea { var content: String var quality: Quality}

enum Quality { case Great case Average case Worst}

@EliSawic

Non-Terminating• Next

@EliSawic

Terminating

• Completed

• Failed

• Interrupted (Reactive Cocoa)

@EliSawic

Presentationlet (presentation, presentationObserver) = Signal<Idea, NoError>.pipe()

let content = "This presentation is a signal"let idea = Idea(content: content, quality: .Great)

presentationObserver.send(value: idea)presentationObserver.sendCompleted()

@EliSawic

Observingpresentation.observeValues { idea in remember(idea: idea)}presentation.observeCompleted { print("Time for a break")}

@EliSawic

Only great ideaslet greatIdeas = presentation.filter { idea in idea.quality == .Great}greatIdeas.observeValues { greatIdea in remember(idea: greatIdea)}

@EliSawic

Positive listenerlet greatPresentation = presentation.map { idea -> Idea in var greatIdea = idea greatIdea.quality = .Great return greatIdea}

@EliSawic

Signal producer

@EliSawic

Represents a tasks

@EliSawic

Possible side effects

@EliSawic

Does not start it's work if not asked

@EliSawic

Run presentationfunc runPresentation() -> SignalProducer<Idea, NoError> { return SignalProducer { observer, _ in observer.send(value: idea1) observer.send(value: idea2) ... observer.sendCompleted() }}

@EliSawic

Work with presentationrunPresentation().startWithValues { idea in print(idea)}

runPresentation().startWithSignal { (signal, _) in signal.observeValues({ idea in print(idea) })

signal.observeCompleted { print("Finally...") }}

@EliSawic

Cold vs Hot

@EliSawic

Properties

@EliSawic

Mutable Propertylet firstSlide = Slide(number: 1)let slide = MutableProperty<Slide>(firstSlide)slide.producer.startWithValues { (text) in print(text)}slide.value = Slide(number: 2)

@EliSawic

Bindings

@EliSawic

Binding examplelet slideNumber = MutableProperty<Int>(0)let (signal, _) = Signal<Slide, NoError>.pipe()

slideNumber <~ signal.map { return $0.number }

@EliSawic

Binding examplelet (signal, _) = Signal<Slide, NoError>.pipe()

label.reactive.text <~ signal.map { return "Slide: \($0.number)" }

@EliSawic

Schedulers

@EliSawic

Know where you aresignal.observe(on: QueueScheduler.main).observeValues { idea in print("Performing UI updates")}

@EliSawic

Memory Management

@EliSawic

Disposables

@EliSawic

Free your memorylet disposable = signal.observeValues { value in ...}

disposable.dispose()

@EliSawic

Release your producerslet disposable = producer.startWithValues { value in ...}

disposable.dispose()

@EliSawic

Example

@EliSawic

@EliSawic

How does it work?

@EliSawic

Is name valid?let isValidNameSignal = nameSignal.map { (name) -> Bool in return name.characters.count > 2}

@EliSawic

Is surname valid?let isValidSurnameSignal = surnameSignal.map { (surname) -> Bool in return surname.characters.count > 2}

@EliSawic

Is mail valid?let isValidMailSignal = 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

Combine Latestlet formDataSignal = combineLatest( isValidNameSignal, isValidSurnameSignal, isValidMailSignal)

@EliSawic

Is form valid?let isValidFormSignal = formDataSignal.map { (isValidName, isValidSurname, isValidMail) -> Bool in return isValidMail && isValidSurname && isValidMail}

@EliSawic

Update the stateisValidFormSignal.observeValues { isValid in updateButtonWith(state: isValid)}

@EliSawic

Bindinglet isValidForm = MutableProperty<Bool>(false)

isValidForm <~ isFormValidSignal

@EliSawic

Conclusion

@EliSawic

Thank you for your attention!sendCompleted()

@EliSawic