Successfully reported this slideshow.

Reactive Collections

2

Share

Upcoming SlideShare
Monadologie
Monadologie
Loading in …3
×
1 of 75
1 of 75

Reactive Collections

2

Share

Download to read offline

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

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

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Related Audiobooks

Free with a 14 day trial from Scribd

See all

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!

×