reactive collections
DESCRIPTION
Description of the Reactive Collections framework for event-driven, reactive and distributed programming, and the real-time game engine use case. See the game demos on YouTube: http://www.youtube.com/channel/UCoyqnhi_BdpLrBVMvkNIMMwTRANSCRIPT
1
Containers and Aggregates, Mutators and Isolates
for Reactive Programming
Aleksandar Prokopec, Philipp Haller, Martin Odersky
Reactive Collections http://reactive-collections.com
2
Reactive
3
4
5
Observables (event streams)
6
Observables (event streams)
• declarative
val log = messages
.filter(_.length < 100)
.scan(_ + “\n” + _)
7
Observables (event streams)
• declarative
val log = messages
.filter(_.length < 100)
.scan(_ + “\n” + _)
var log = “”
def receive = {
case s: String =>
if (s.length < 100)
log = log + “\n” + s
}
8
Actors
• encapsulate mutable state
9
Actors
• encapsulate mutable state
var log = “”
def receive = {
case s: String =>
if (s.length < 100)
log = log + “\n” + s
}
10
Reactive collections
Isolate Reactive Channel
Actor ?
ActorRef
? Observable Observable
11
Reactive values
Reactive[T]
12
val ticks: Reactive[Long]
13
ticks 1
1
2
2
3
3
4
4
60
60
61
61
ticks onEvent { x => log.debug(s”tick no.$x”) }
14
1 2 3 4 60 61
tick no.1
tick no.2
tick no.3
tick no.4
tick no.60
tick no.61
...
ticks foreach { x => log.debug(s”tick no.$x”) }
15
1 2 3 4 60 61
16
for (x <- ticks) { log.debug(s”tick no.$x”) }
Single-threaded!
17
Reactive combinators
for (x <- ticks) yield { x / 60 }
18
val seconds: Reactive[Long] = for (x <- ticks) yield { x / 60 }
19
60 61
val seconds: Reactive[Long] = for (x <- ticks) yield { x / 60 }
20
ticks 1
1
2
2
3
3 60 61
seconds
0 0 0 1 1
ticks
seconds
0 0 0 1 1
val days: Reactive[Long] = seconds.map(_ / 86400)
21
val days: Reactive[Long] = seconds.map(_ / 86400) val secondsToday =
22
val days: Reactive[Long] = seconds.map(_ / 86400) val secondsToday = (seconds zip days) { (s, d) => s – d * 86400 } 23
val angle = secondsInDay.map(angleFunc)
24
val angle = secondsInDay.map(angleFunc) val light = secondsInDay.map(lightFunc)
25
26
27
val rotate = keys
a ↓ shift ↓ a ↑ shift ↑ pgup ↓ pgup ↑ keys
28
val rotate = keys.filter(_ == PAGEUP)
a ↓ shift ↓ a ↑ shift ↑ pgup ↓ pgup ↑ keys
pgup ↓ pgup ↑ filter
29
val rotate = keys.filter(_ == PAGEUP) .map(_.down)
a ↓ shift ↓ a ↑ shift ↑ pgup ↓ pgup ↑ keys
pgup ↓ pgup ↑ filter
true false map
30
if (rotate()) viewAngle += 1
true false map
31
Signals
32
trait Signal[T] extends Reactive[T] { def apply(): T }
33
val rotate = keys.filter(_ == PAGEUP) .map(_.down) .signal(false)
true false map
signal
34
val rotate: Signal[Boolean] = keys.filter(_ == PAGEUP) .map(_.down) .signal(false)
true false map
signal
35
val rotate: Signal[Boolean] val ticks: Reactive[Long]
ticks
36
val rotate: Signal[Boolean] val ticks: Reactive[Long]
ticks
rotate
37
val rotate: Signal[Boolean] val ticks: Reactive[Long] val viewAngle: Signal[Double] =
ticks
rotate
viewAngle
38
val rotate: Signal[Boolean] val ticks: Reactive[Long] val viewAngle: Signal[Double] = ticks.scanPast(0.0)
ticks
rotate
viewAngle
39
val rotate: Signal[Boolean] val ticks: Reactive[Long] val viewAngle: Signal[Double] = ticks.scanPast(0.0) { (a, _) => if (rotate()) a + 1 else a }
ticks
rotate
viewAngle
40
41
val velocity = ticks.scanPast(0.0) { (v, _) => } val viewAngle =
42
val velocity = ticks.scanPast(0.0) { (v, _) => if (rotate()) v + 1 } val viewAngle =
43
val velocity = ticks.scanPast(0.0) { (v, _) => if (rotate()) v + 1 else v – 0.5 } val viewAngle =
44
val velocity = ticks.scanPast(0.0) { (v, _) => if (rotate()) v + 1 else v – 0.5 } val viewAngle = velocity.scanPast(0.0)(_ + _)
45
46
Reactive mutators
47
class Matrix { def apply(x: Int, y: Int): Double def update(x: Int, y: Int, v: Double) }
48
val screenMat: Signal[Matrix] = (projMat zip viewMat)(_ * _) val invScreenMat = screenMat.map(_.inverse)
49
Reactive[immutable.Matrix[T]]
50
val screenMat: Signal[Matrix] = (projMat zip viewMat)(_ * _) val invScreenMat = screenMat.map(_.inverse)
(4*4*8 + 16 + 16)*4*100 = 64 kb/s
51
val screenMat = Mutable(new Matrix) (projMat, viewMat).mutate(screenMat) { (p, v) => screenMat().assignMul(p, v) } val invScreenMat = Mutable(new Matrix) screenMat.mutate(invScreenMat) { m => invScreenMat().assignInv(m) }
52
Reactive collections
53
54
val selected: Reactive[Set[Character]]
55
val selected: ReactSet[Character]
56
trait ReactSet[T] extends ReactContainer[T] { def apply(x: T): Boolean }
57
trait ReactContainer[T] { def inserts: Reactive[T] def removes: Reactive[T] }
58
A reactive collection is a pair
of reactive values
59
val selected = new ReactHashSet[Character]
60
61
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c)))
62
class ReactContainer[T] { self => def inserts: Reactive[T] def removes: Reactive[T] def map[S](f: T => S) = new ReactContainer[S] { def inserts: Reactive[T] = self.inserts.map(f) def removes: Reactive[T] = self.removes.map(f) } }
63
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .to[ReactHashMap]
64
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .to[ReactHashMap]
65
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .to[ReactHashMap]
66
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .to[ReactHashMap]
67
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .react.to[ReactHashMap]
68
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .react.to[ReactHashMap]
69
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .react.to[ReactHashMap]
70
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .react.to[ReactHashMap]
71
Isolates
72
UI isolate
class UI extends Isolate[UI.Message] { val frames = source.filter(_ == UI.Frame) val exit = source onCase { case UI.Exit => exit() } }
Source
73
UI Isolate
Source
AI Isolate
Source
Channel[AI.Message]
Channel[UI.Message]
74
Reactive collections
Isolate Reactive Channel
Actor ?
ActorRef
? Observable Observable
75
Thank you!