an introduction to reactive programming (2)stg-tud.github.io/sedc/lecture/ws17-18/rp2.pdfguido...

64
Guido Salvaneschi: introduction to reactive programming An Introduction to Reactive Programming (2) Prof. Guido Salvaneschi

Upload: others

Post on 20-May-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

AnIntroductiontoReactiveProgramming(2)

Prof.GuidoSalvaneschi

Page 2: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Outline

• Analysisoflanguagesforreactiveapplications• Detailsofreactiveframeworks• Advancedconversionfunctions• Examplesandexercises• Relatedapproaches

Page 3: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

REACTIVEAPPLICATIONS:ANALYSIS

Page 4: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

• Atransformational system– Acceptsinput,performscomputationonit,producesoutput,andterminates

– Compilers,shelltools,scientificcomputations

• Areactive system– Continuouslyinteractswiththeenvironment– Updatesitsstate

SoftwareTaxonomy

Page 5: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

HowtoimplementReactiveSystems?

• ObserverPatter– Thetraditional wayinOOlanguages

• Language-levelevents– Event-basedlanguages

• Signals,vars,eventsandtheircombination– Reactivelanguages

Page 6: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

OBSERVERPATTERN:ANALYSIS

Page 7: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

The(good?old)ObserverPatternbooleanhighTemp;booleansmoke;

voidInit(){tempSensor.register(this);smokeSensor.register(this);

}

voidnotifyTempReading(TempEvente){highTemp=e.getValue()>45;if(highTemp&&smoke){

alert.start();}

}

voidnotifySmokeReading(SmokeEvente){smoke=e.getIntensity()>0.5;if(highTemp&&smoke){

alert.start();}

}

Callbackfunctions

State

Controlstatements

Registration

Callbackfunctions

Controlstatements

Page 8: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Observerforchangepropagation

• Mainadvantage:

DecouplethecodethatchangesavalueXfromthecodethatupdatesthevaluesdependingonX

– “Source”doesn’tknowabout“Constraint”

– Temp/Smokesensorsdonotknowaboutfiredetector

Page 9: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

• Eventsareoftenusedtoenforcedatadependencyconstraints

– booleanhighTemp:=(temp.value>45);

The(good?old)ObserverPattern

Page 10: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Theexample

val a=3

val b=7

val c=a+b

a=4b=8

Page 11: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

TheExample:Observertrait Observable{val observers=scala.collection.mutable.Set[Observer]()def registerObserver(o:Observer)={observers+=o}def unregisterObserver(o:Observer)={observers-=o}def notifyObservers(a:Int,b:Int)={observers.foreach(_.notify(a,b))}}trait Observer{def notify(a:Int,b:Int)}

class Sources extends Observable{var a=3var b=7}class Constraint(a:Int,b:Int)extends Observer{var c=a+bdef notify(a:Int,b:Int)={c=a+b}}

val s=new Sources()val c=new Constraint(s.a,s.b)s.registerObserver(c)s.a =4s.notifyObservers(s.a,s.b)s.b =8s.notifyObservers(s.a,s.b)

Page 12: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

The(good?old)ObserverPattern

Longstoryofcriticism…

• Inversionofnatural dependencyorder– “Sources”updates“Constraint”butinthecode“Constraint”calls“Sources”(toregisteritself)

• Boilerplatecode trait Observable{val observers=scala.collection.mutable.Set[Observer]()def registerObserver(o:Observer)={observers+=o}def unregisterObserver(o:Observer)={observers-=o}

….tempSensor.register(this);smokeSensor.register(this);

Page 13: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

The(good?old)ObserverPattern

• Reactionsdonotcompose,returnvoid– Howtodefinenewconstraintsbasedontheexistingones

class Constraint(a:Int,b:Int)… {var c=a+bdef notify(a:Int,b:Int)={c=a+b

}}

class Constraint2(d:Int)…{var d=c*7def notify(d:Int)={d=c*7

}}

+ =??

Page 14: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

The(good?old)ObserverPattern

• Scatteringandtanglingoftriggeringcode

– Failtoupdateallfunctionallydependentvalues.

– Valuesareoftenupdatetoomuch(defensively)

val s=new Sources()val c=new Constraint(s.a,s.b)s.registerObserver(c)s.a =4s.notifyObservers(s.a,s.b)s.b =8s.notifyObservers(s.a,s.b)

change(b)view.update()............

change(a)view.update()..................

..................change(c)view.update()

VIEWA B C

DATAABC

Page 15: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

The(good?old)ObserverPattern

• Imperativeupdatesofstate

• Noseparationofconcerns

class Constraint(a:Int,b:Int)extends Observer{var c=a+bdef notify(a:Int,b:Int)={c=a+b}}

class Constraint(a:Int,b:Int)extends Observer{var c=a+bdef notify(a:Int,b:Int)={c=a+b}}

Updatelogic+

Constraintdefinition

Page 16: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

EVENT-BASEDLANGUAGES:ANALYSIS

Page 17: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Event-basedLanguages

• Language-levelsupportforevents– C#,Ptolemy,REScala,…

– Imperativeevents

– Declarativeevents,||,&&,map,…

val update=Evt[Unit]()

val changed[Unit]=resized||moved||afterExecSetColorval invalidated[Rectangle]=changed.map(_=>getBounds())

val e=Evt[Int]()e+={println(_)}e(10)

Page 18: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Event-basedLanguages

val update=Evt[Unit]()val a=3val b=7val c=a+b//Functionaldependency

update+=(_=>{c=a+b})

a=4update()b=8update()

Page 19: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Event-basedLanguages

• Morecomposable– Declarativeeventsarecomposedbyexistingevents(notintheexample)

• Lessboilerplatecode– Applicationsareeasiertounderstand

• GoodintegrationwithObjectsandimperativestyle:– Imperativeupdatesandsideeffects– Inheritance,polymorphism,…

Page 20: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Event-basedLanguages

• Dependenciesstillencodedmanually– Handlerregistration

• Updatesmustbeimplementedexplicitly– Inthehandlers

• Notificationsarestillerrorprone:– Toorarely/toooften

class Connector(val start:Figure,val end:Figure){start.changed +=updateStartend.changed +=updateEnd...def updateStart(){...}def updateEnd(){...}…

Page 21: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

REACTIVELANGUAGES:ANALYSIS

Page 22: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

ReactiveLanguages

• Functional-reactiveprogramming(FRP)-- Haskell– Time-changingvaluesasdedicatedlanguageabstractions.

[Functionalreactiveanimation,ElliottandHudak.ICFP’97]

• Morerecently:– FrTime [Embeddingdynamicdataflowinacall-by-valuelanguage,

CooperandKrishnamurthi,ESOP’06]

– Flapjax [Flapjax:aprogramminglanguageforAjaxapplications.Meyerovich etal.OOPSLA’09]

– Scala.React [I.Maier etal,DeprecatingtheObserverPatternwithScala.React.Technicalreport,2012]

Page 23: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

ReactiveLanguagesandFRP

• Signals– Dedicatedlanguageabstractionsfortime-changing values

• AnalternativetotheObserverpatternandinversionofcontrol

val a=Var(3)val b=Var(7)val c=Signal{a()+b()}

println(c.now)>10a()=4println(c.now)>11

Page 24: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

title="ReactiveSwingApp"val label=new ReactiveLabelval button=new ReactiveButton

val nClicks =button.clicked.fold(0){(x,_)=>x+1}

label.text =Signal{(if (nClicks()==0)"No"else nClicks())+"buttonclicksregistered"}

button.text =Signal{"Clickme"+(if (nClicks()==0)"!" else "again" )}

contents=new BoxPanel(Orientation.Vertical){contents+=buttoncontents+=label

}

/*Createthegraphics*/title="ReactiveSwingApp“val button=newButton{text="Clickme!"}val label=new Label{text="Nobuttonclicksregistered"}contents=new BoxPanel(Orientation.Vertical){contents+=buttoncontents+=label}

/*Thelogic*/listenTo(button)var nClicks =0reactions+={case ButtonClicked(b)=>nClicks +=1label.text ="Numberofbuttonclicks:"+nClicksif (nClicks >0)button.text ="Clickmeagain"

}

Page 25: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

ReactiveLanguages• Easiertounderstand

– Declarativestyle– Localreasoning– Noneedtofollowthecontrolflow

toreverseengineertheconstraints• Dependentvaluesareautomaticallyconsistent

– Noboilerplatecode– Noupdateerrors(noupdates/updatedefensively)– Noscatteringandtanglingofupdatecode

• Reactivebehaviorsarecomposable– Incontrasttocallbacks,whichreturnvoid

Page 26: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Signalsallowagooddesign.Buttheyarefunctional(only).

Functionalprogrammingisgreat!But…

Thesadstory:– Theworldisevent-based,…– Often imperative,…– AndmostlyObject-oriented

NOW…val a=Var(3)val b=Var(7)val c=Signal{a()+b()}val d=Signal{2*c()}val e =Signal{"Result:" +d()}

Page 27: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

ReactiveLanguages

• Inpractice,botharesupported:– Signals(continuous)– Events(discrete)

• Conversionfunctions– Bridgesignalsandevents– Allowinteractionwithobjectsstateandimperativecode

Changed :: Signal[T] -> Event[T]Latest :: Event[T] -> Signal[T]

Page 28: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

ADVANCEDINTERFACEFUNCTIONS

Page 29: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Fold

• Createsasignalbyfoldingeventswithafunctionf– Initiallythesignalholdstheinit value.

• fold[T,A](e:Event[T],init:A)(f:(A,T)=>A):Signal[A]

val e=Evt[Int]()val f=(x:Int,y:Int)=>(x+y)val s:Signal[Int]=e.fold(10)(f)assert(s.now ==10)e(1)e(2)assert(s.now ==13)

Page 30: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

LatestOption

• Variantoflatest.– TheOptiontypeforthecasetheeventdidnotfireyet.– LatestvalueofaneventasSome(value)orNone

• latestOption[T](e:Event[T]):Signal[Option[T]]

val e=Evt[Int]()val s:Signal[Option[Int]]=e.latestOption(e)assert(s.now ==None)e(1)assert(s.now ==Option(1))e(2)assert(s.now ==Option(2))e(1)assert(s.now ==Option(1))

Page 31: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Last

• Generalizeslatest– Returnsasignalwhichholdsthelastn events– Initiallyanemptylist

• last[T](e:Event[T],n:Int):Signal[List[T]]

val e=Evt[Int]()val s:Signal[List[Int]]=e.last(5)

assert(s.now ==List())e(1)assert(s.now ==List(1))e(2)assert(s.now ==List(2,1))

e(3);e(4);e(5)assert(s.now ==List(5,4,3,2,1))e(6)assert(s.now ==List(6,5,4,3,2))

Page 32: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

List

• Collectstheeventvaluesina(evergrowing)list• Usecarefully…potentialmemoryleaks

• list[T](e:Event[T]):Signal[List[T]]

Page 33: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Iterate

• Repeatedlyappliesf toavaluewhene occurs– Thereturnsignalisconstant,basedoninit– Fissimilartoahandler

• iterate[A](e:Event[_],init:A)(f:A=>A):Signal[A]

var test:Int =0val e=Evt[Int]()val f=(x:Int)=>{test=x;x+1}val s:Signal[Int]=e.iterate(10)(f)

e(1)assert(test==10)assert(s.now ==10)e(2)assert(test==11)assert(s.now ==10)e(1)assert(test==12)assert(s.now ==10)

Page 34: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Count

• Returnsasignalthatcountstheoccurrencesofe– Initially,thesignalholds0.– Theargumentoftheeventisdiscarded.

• count(e:Event[_]):Signal[Int]

val e=Evt[Int]()val s:Signal[Int]=e.countassert(s.now ==0)e(1)e(3)assert(s.now ==2)

Page 35: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

title="ReactiveSwingApp"val label=new ReactiveLabelval button=new ReactiveButton

val nClicks =button.clicked.fold(0){(x,_)=>x+1}

label.text =Signal{(if (nClicks()==0)"No"else nClicks())+"buttonclicksregistered"}

button.text =Signal{"Clickme"+(if (nClicks()==0)"!" else "again" )}

contents=new BoxPanel(Orientation.Vertical){contents+=buttoncontents+=label

}

/*Createthegraphics*/title="ReactiveSwingApp“val button=newButton{text="Clickme!"}val label=new Label{text="Nobuttonclicksregistered"}contents=new BoxPanel(Orientation.Vertical){contents+=buttoncontents+=label}

/*Thelogic*/listenTo(button)var nClicks =0reactions+={case ButtonClicked(b)=>nClicks +=1label.text ="Numberofbuttonclicks:"+nClicksif (nClicks >0)button.text ="Clickmeagain"

}

Page 36: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Snapshot

• Returnsasignalupdatedonlywhene fires.– Otherchangesofs areignored.– Thesignalisupdatedtothecurrentvalueofs.– Returnsthesignalitselfbeforee fires

• snapshot[V](e:Event[_],s:Signal[V]):Signal[V]val e=Evt[Int]()val v=Var(1)val s1=Signal{v()+1}val s=e.snapshot(s1)

assert(s.now ==2)e(1)assert(s.now ==2)v.set(2)//s1==3assert(s.now ==2)e(1)assert(s.now ==3)

s!?

Page 37: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Change

• Similartochanged– changed[U]:Event[U]– Providesboththeoldandthenewvalueinatuple– change[U]:Event[Diff[U]]

val s=Signal{...}val e:Event[Diff[Int]]=s.changee+=(x:Diff[Int]=>{val (old,nnew):(Int,Int)=x.pair...

})

Page 38: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

ChangedTo

• Similartochanged– Theeventisfiredonlyifthesignalholdsthegivenvalue– Thevalueofeisdiscarded

• changedTo[V](value:V):Event[Unit]

var test=0val v=Var(1)val s=Signal{v()+1}val e:Event[Unit]=s.changedTo(3)e+=((x:Unit)=>{test+=1})

assert(test==0)vset2assert(test==1)vset3assert(test==1)

test!?

Page 39: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Toggle

• Switchesbetweensignalsontheoccurrenceofe.– Thevalueattachedtotheeventisdiscarded– toggle[T](e:Event[_],a:Signal[T],b:Signal[T]):Signal[T]

val e=Evt[Int]()val v1=Var(1)val s1=Signal{v1()+1}val v2=Var(11)val s2=Signal{v2()+1}val s=e.toggle(s1,s2)

assert(s.now ==2)e(1)assert(s.now ==12)v2.set(12)assert(s.now ==13)v1.set(2)assert(s.now ==13)e(1)v1.set(3)assert(s.now ==4)v2.set(13)assert(s.now ==4)

S!?

Page 40: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

switchOnce

• Switchestoanewsignalprovidedasaparameteronce,ontheoccurrenceofe

switchOnce[T](e:Event[_],original:Signal[T],newSignal:Signal[T]):Signal[T]

val e=Evt[Int]()val v1=Var(0)val v2=Var(10)val s1=Signal{v1()+1}val s2=Signal{v2()+1}val s3=e.switchOnce(s1,s2)

assert(s3.now==1)v1.set(1)assert(s3.now==2)e(1)assert(s3.now==11)e(2)v2.set(11)assert(s3.now==12)

Page 41: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Noteontheinterface

• Weshowedthe“nonOO”signatureformostoftheinterfacefunctions– Inpractice,thesignatureisinOOstyle– Oneoftheparametersisthereceiverofthemethod

• Forexample

– Mustbecalledas:snapshot(e,s)//snapshot[V](e:Event[_],s:Signal[V]):Signal[V]

e.snapshot(s)//e.snapshot[V](s:Signal[V]):Signal[V]

Page 42: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

DETAILSONTHEREACTIVEMODEL

Page 43: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Implementation:Challenges

• In-languagereactiveabstractions– DSL/Compiler– Buildthedependencymodel

• Languageruntime– Dependencygraph

• Evaluation• Changepropagation• Modelmaintenance

val e,f,g=Var(1)val d=Var(true)

c=Signal{f()+g()}b=Signal{e()*100}a=Signal{

if(d)celse b

}a

bcd

ef g

Page 44: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

DSLImplementation

• Buildingthegraph– Var(3)->leaf– Var(4)->leaf– “a()+b()”savedinaclosure– Signal{…}->dependentnode

• Signalexpressionevaluation– Reactivevalues ->edges– Signal=resultoftheevaluation

val a=Var(3)val b=Var(4)val c=Signal{a()+b()}

a

c

b

Page 45: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Pullvs.PushModels

f

d

c

a b

y z

h

e

i

g

f

d

c

a b

y z

h

e

i

g

E.g.,REScala,Rx,bacon.js

Page 46: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Temporaryspurious valuesduetopropagationorder.– Updateorderabdc– a()=2b<-4,d<-7,c<-6,d<-10

• Effects:– dredundantlyevaluated2times– Firstvalueofdhasnomeaning– e erroneouslyfiredtwotimes

Glitches

a

b

d

c

val a=Var(1)val b=Signal{a()*2}val c=Signal{a()*3}val d=Signal{b()+c()}val e =d.changed

e

Page 47: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

• Ensuredbyupdatesintopologicalorder– NodesareassignedtolevelsLn– Levelsareupdatesinorder– E.g.,“abcde”or“acbde”

• Technicalsolutions:– Priorityqueue– Nodeswaitforchildrenbeforeevaluating

GlitchFreedom

a

b

d

c

e

L1

L2

L3

L4

Page 48: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

• Dependenciesbasedonruntimeconditions

– Incase c==true,dmustchange:• Ifa changes• Notifb changes

– d dependsona orbbasedon currentvalueofc

– Changedependenciesatruntime

Dynamicdependencies

val a=Var(3)val b=Var(7)val c=Var(false)val d=Signal{if c()a()elseb()

}val e =Signal{2*d()}

a b

d

e

c

Page 49: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

• Easierimplementation• Redundantevaluations– d isexecuteduponbassignments

– eveniftheddoesnotchange

(Lackof)Dynamicdependencies

val a=Var(3)val t=Var(7)val c=Var(true)val d=Signal{if c()a()elseb()

}while(true){b()=…//systemtime}a b

d

e

c

Page 50: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

• Rejectloops– Responsibilitytotheprogrammer(REScala,Flapjax)– Loopsrejectedbythecompiler

• Acceptloops:whichsemantics?– Delaytothenextpropagationround– Fixpointsemantics

• Timeconsuming?• Termination?

AboutLoops

val x=Signal{y()+1}val y=Signal{x()+1}

Page 51: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

EXAMPLESANDEXERCISES

Page 52: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Example:InterfaceFunctions

• Countmouseclicks

• Betterwithinterfacefunctions

• Evenbetter:usecount!

val click:Event[(Int,Int)]=mouse.clickval nClick:Signal[Int]=click.fold(0)((x,_)=>x+1)

val click:Event[(Int,Int)]=mouse.clickval nClick=Var(0)click+={_=>nClick.transform(_+1) //nClick()=nClick.now +1}

val click:Event[(Int,Int)]=mouse.clickval nClick:Signal[Int]=click.count()

Concisenessvs.

Generality

Page 53: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Example:InterfaceFunctions

• Holdthepositionofthelastclickinasignal

• Betterwithinterfacefunctions

val clicked:Event[Unit]=mouse.clickedval position:Signal[(Int,Int)]=mouse.position

val clicked:Event[Unit]=mouse.clickedval position:Signal[(Int,Int)]=mouse.positionvar lastClick =Var(0,0)clicked+={_=>lastClick()=position()}

val lastClick:Signal[(Int,Int)]=positionsnapshotclicked

Page 54: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

MeanOverWindow

• EventscollectDouble valuesfromasensor• Meanoverashiftingwindowofthelastn events• Printthemeanonlywhenitchanges

e(2)e(1)e(3)e(2)e(1)e(3)e(4)e(1) e(3)e(4)

n

OLD NEW

Page 55: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

MeanOverWindow• Meanoverashiftingwindowofthelastnevents• Printthemeanonlywhenitchanges

val e=Evt[Double]

val window=e.last(5)valmean=Signal{window().sum/window().length}mean.changed +={println(_)}

e(2);e(1);e(3);e(4);e(1);e(1)

2.01.52.02.52.22.0

Page 56: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Example:InterfaceFunctions

/*Composereactivevalues*/valmouseChangePosition =mouseMovedE ||mouseDraggedEvalmousePressedOrReleased =mousePressedE ||mouseReleasedEvalmousePosMoving:Signal[Point]=mouseChangePosition.latest(new Point(0,0))val pressed:Signal[Boolean]=mousePressedOrReleased.toggle(Signal{false },Signal{true })

Page 57: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

DependencyGraph/*Composereactivevalues*/valmouseChangePosition =mouseMovedE ||mouseDraggedEvalmousePressedOrReleased =mousePressedE ||mouseReleasedEvalmousePosMoving:Signal[Point]=mouseChangePosition.latest(new Point(0,0))val pressed:Signal[Boolean]=mousePressedOrReleased.toggle(Signal{false },Signal{true })

mouseMoved mouseDraggedE

mouseChangePosition

mousePressedE mouseReleasedE

mousePressedOrReleased

mousePosMoving

Signal{false } Signal{true }

pressed

Page 58: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Example:TimeElapsing

• Wewanttoshowtheelapsingtimeonadisplay• (second,minute,hour,day)

(0,0,0,0)(1,0,0,0)(2,0,0,0)…(59,0,0,0)(0,1,0,0)(1,1,0,0)(2,1,0,0)…(59,1,0,0)(0,2,0,0)

(1,2,0,0)…(59,59,0,0)(0,0,1,0)…(59,59,23,0)(0,0,0,1)….

Page 59: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

object TimeElapsing extends App{

println("start!")

val tick=Var(0)val second=valminute=val hour=val day=

while(true){Thread.sleep(0)println((second.now,minute.now,hour.now,day.now))tick.set(tick.now +1)}}

Butdayisstillcircular.Atsomepointday==0again

Also,conceptuallyhardtofollow

TimeElapsing:FirstAttempt

Signal{tick()%60}Signal{tick()/60%60}

Signal{tick()/(60*60)%(60*60)}Signal{tick()/(60*60*24)%(60*60*24)}

Page 60: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

TimeElapsing

object AdvancedTimeElapsing extends App{println("start!")val tick=Evt[Unit]()

val numTics =val seconds=valminutes=val hours=val days=

while(true){Thread.sleep(0)println((seconds.now,minutes.now,hours.now,days.now))tick(())//tick.fire()}}

tick.countSignal{numTics()%60}Signal{seconds.changedTo(0).count.apply %60}

Signal{minutes.changedTo(0).count.apply %24}hours.changedTo(0).count

Uses.changedTo(v)- Firesandeventifsholdsve.count- Countstheoccurrencesofe

Page 61: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Exercise:drawdependencygraph

• Whichvariablesareaffectedbyachangetotick?

tick

numTics

seconds

seconds.changedTo(0)

minutes

minutes.changedTo(0)

hours

hours.changedTo(0)

days

val tick=Evt[Unit]()val numTics =tick.countval seconds=Signal{numTics()%60}valminutes=Signal{seconds.changedTo(0).count()%60}val hours=Signal{minutes.changedTo(0).count()%24}val days=hours.changedTo(0).count

(Somenodesomitted)

Page 62: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

Example:SmashingParticles

• Particles– Getbigger– Movebottom-right

Page 63: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

val toDraw =ListBuffer[Function1[Graphics2D,Unit]]()typeDelta=Point

class Oval(center:Signal[Point],radius:Signal[Int]){toDraw +=((g:Graphics2D)=>{g.fillOval(center.now.x,center.now.y,radius.now,radius.now)})

}

val base=Var(0)val time=Signal{base()%200}//timeiscyclic:)

val point1=Signal{new Point(20+time(),20+time())}new Oval(point1,time)val point2=Signal{new Point(40+time(),80+time())}new Oval(point2,time)… override defmain(args:Array[String]){

while (true){frame.repaintThreadsleep20base()=base.now +1

}}

• Signalsareusedinsideobjects!

Page 64: An Introduction to Reactive Programming (2)stg-tud.github.io/sedc/Lecture/ws17-18/RP2.pdfGuido Salvaneschi: introduction to reactive programming •A transformationalsystem –Accepts

GuidoSalvaneschi:introductiontoreactiveprogramming

QUESTIONS?