Introduction To Reactive Programming
Introduction To Reactive Programming
Introduction to Reactive
Programming
Prof. Guido Salvaneschi
• A reactive system
– Continuously interacts with the environment
– Updates its state
• Reactive systems:
– Represent the current state of interaction
– Reflect changes of the external world during interaction
• Typical operations
– Detect events/notifications and react
– Combine reactions
– Propagate updates/changes
• Event handling:
– 30% of code in desktop applications
– 50% of bugs reported during production cycle
• Books 2014-16
void Init() {
tempSensor.register(this);
smokeSensor.register(this); Registration
}
BEEEEP!
public Beeper() {
super(new BorderLayout()); BEEEEP!
button = new JButton("Click Me");
button.setPreferredSize(new Dimension(200, 80));
add(button, BorderLayout.CENTER);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
Toolkit.getDefaultToolkit().beep();
}
private static void createAndShowGUI() { // Create the GUI and show it.
JFrame frame = new JFrame("Beeper"); //Create and set up the window.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new Beeper(); //Create and set up the content pane.
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack(); //Display the window.
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater( new Runnable() { public void run() {createAndShowGUI();}});
}
}
val e1 = Evt[Unit]()
val e2 = Evt[Int]()
val e3 = Evt[String]()
val e4 = Evt[Boolean]()
class Foo
val e6 = Evt[Foo]()
val e1 = Evt[(Int,Int)]()
val e2 = Evt[(String,String)]()
val e3 = Evt[(String,Int)]()
val e4 = Evt[(Boolean,String,Int)]()
val e = Evt[(Int,String)]()
e += (x => {
println(x._1)
println(x._2)
})
e += (x: (Int,String) => {
println(x)
})
val e = Evt[Unit]()
e += { x => println(“Fired!”) }
e += { (x: Unit) => println(“Fired!”) }
val e = Evt[Int]
e += m1 _
e(10)
val e1 = Evt[Int]()
val e2 = Evt[Boolean]()
val e3 = Evt[(Int,String)]()
e1(10)
e2(false)
e3((10,"Hallo"))
val e = Evt[Int]()
e += { x => println(x) }
e(10)
e(11)
-- output ----
10
11
val e = Evt[Int]()
e += { x => println(x) }
e += { x => println("n: " + x)}
e(10)
e(11)
-- output ----
10
n: 10
11
n: 11
-- output ----
10
n: 10
n: 10
• Examples:
– mouseClickE -> museClickOnShape
– mouseClose, keyboardClose -> closeWindow
• Can we solve this problem enhancing the language?
Guido Salvaneschi: introduction to reactive programming
Declarative Events
• Declarative events are defined by a combination of
other events.
val e3 = e1 || e2
val e4 = e1 && ((x: Int)=> x>10)
val e5 = e1 map ((x: Int)=> x.toString)
-- output ----
10
10
val e = Evt[Int]()
val e_AND: Event[Int] = e && ((x: Int) => x>10)
e_AND += ((x: Int) => println(x))
e(5)
e(15)
-- output ----
15
...
def run {
var currentTemp = measureTemp()
while(!stop) {
val newTemp = measureTemp()
if (newTemp != currentTemp) {
tempChanged(newTemp)
currentTemp = newTemp
}
sleep(100)
}
}
}
update += ( _ =>{
var a = 3 c = a + b
var b = 7 })
val c = a + b
a = 4
a = 4 update()
b = 8 b = 8
update()
val a = 3 val a = 3
val b = 7 val b = 7
val c = a + b // Statement val c := a + b // Constraint
println(c) println(c)
> 10 > 10
a= 4 a= 4
println(c) println(c)
> 10 > 11
…
val a = Var(3) d
val b = Var(7)
val c = Signal{ a() + b() }
val d = Signal { 2 * c() } c
…
a b
// Multiple vars
// in a signal expression c
val a = Var(0)
val b = Var(0)
val s = Signal{ a() + b() } a b
val a = Var(0)
val b = Var(0)
val c = Var(0)
val t = Signal{ s() * c() + 10 } // Mix signals and vars in signal expressions
val a = Var(0)
val b = Var(2)
val c = Var(true)
val s: Signal[Int] = Signal{ a() + b() }
val t: Signal[Boolean] = Signal{ !c() }
label.text = Signal { ( if (nClicks() == 0) "No" else nClicks() ) + " button clicks registered" }
button.text = Signal { "Click me" + (if (nClicks() == 0) "!" else " again " )}
val point1 = Signal{ new Point(20+ cyclicTime (), 20+ cyclicTime ()) }
new Oval(point1, cyclicTime )
… // 4 times
• Conversion functions
bridge signals and events SIGNALS
EVENTS
while (true) {
Thread sleep 20
time() = time.now + 1
}
-- output --
10
20
30
40
...
val v1 = Var(4)
val v2 = Var(2)
val s1 = Signal{ v1() + v2() }
val s2 = Signal{ s1() / 3 }
assert(s2.now ==
assert(s2.now == 2)
v1()=1
assert(s2.now ==
assert(s2.now == 1)
var test = 0
val v1 = Var(4)
val v2 = Var(2)
val s1 = Signal{ v1() + v2() }
s1.changed += ((x: Int)=>{test+=1})
assert(test ==
assert(test == 0)
v1()=1
assert(test == 1)
assert(test ==
val e = Evt[Int]()
val v1 = Var(4)
val v2 = Var(2)
val s1 = e.latest(0)
val s2 = Signal{ v1() + v2() + s1() }
assert(s2.now ==
assert(s2.now == 6)
e(2)
assert(s2.now == 8)
assert(s2.now ==
e(1)
assert(s2.now ==
assert(s2.now == 7)
– () creates a dependency. a b
Use only in signal expressions
– now returns the current value val a = Var(2)
val b = Var(3)
val c = Signal{ a.now + b() }