Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
1 
Containers and Aggregates, 
Mutators and Isolates 
for Reactive Programming 
Aleksandar Prokopec, Philipp Haller, Marti...
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 = “”...
8 
Actors 
• encapsulate mutable state
9 
Actors 
• encapsulate mutable state 
var log = “” def receive = { case s: String => if (s.length < 100) log = log + “n”...
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 ...
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 
...
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 ↑...
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 
rota...
39 
val rotate: Signal[Boolean] val ticks: Reactive[Long] val viewAngle: Signal[Double] = ticks.scanPast(0.0) { (a, _) => ...
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....
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 ...
51 
val screenMat = Mutable(new Matrix) (projMat, viewMat).mutate(screenMat) { (p, v) => screenMat().assignMul(p, v) } val...
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 ReactC...
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[ReactHa...
68 
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .react.to[ReactHashMa...
69 
val selected = 
new ReactHashSet[Character] 
val decorations = selected 
.map(c => (c, decoFor(c))) 
.react.to[ReactHa...
70 
val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c))) .react.to[ReactHashMa...
71 
Isolates
72 
UI isolate 
class UI extends Isolate[UI.Message] { val frames = source.filter(_ == UI.Frame) val exit = source onCase ...
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!
Upcoming SlideShare
Loading in …5
×

Reactive Collections

914 views

Published on

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_BdpLrBVMvkNIMMw

Published in: Software
  • Be the first to comment

Reactive Collections

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

×