Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Reactive Collections

Reactive Collections

Description of the reactive collections framework from the Scala 2014 workshop.

Aleksandar Prokopec

July 30, 2014
Tweet

More Decks by Aleksandar Prokopec

Other Decks in Programming

Transcript

  1. 1 Containers and Aggregates, Mutators and Isolates for Reactive Programming

    Aleksandar Prokopec, Philipp Haller, Martin Odersky
  2. 4

  3. 6 Observables (event streams) • declarative val log = messages

    .filter(_.length < 100) .scan(_ + “\n” + _)
  4. 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 }
  5. 9 Actors • encapsulate mutable state var log = “”

    def receive = { case s: String => if (s.length < 100) log = log + “\n” + s }
  6. 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 ...
  7. 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
  8. val days: Reactive[Long] = seconds.map(_ / 86400) val secondsToday =

    (seconds zip days) { (s, d) => s – d * 86400 } 23
  9. 26

  10. 27 val rotate = keys a ↓ shift ↓ a

    ↑ shift ↑ pgup ↓ pgup ↑ keys
  11. 28 val rotate = keys.filter(_ == PAGEUP) a ↓ shift

    ↓ a ↑ shift ↑ pgup ↓ pgup ↑ keys pgup ↓ pgup ↑ filter
  12. 29 val rotate = keys.filter(_ == PAGEUP) .map(_.down) a ↓

    shift ↓ a ↑ shift ↑ pgup ↓ pgup ↑ keys pgup ↓ pgup ↑ filter true false map
  13. 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
  14. 40

  15. 42 val velocity = ticks.scanPast(0.0) { (v, _) => if

    (rotate()) v + 1 } val viewAngle =
  16. 43 val velocity = ticks.scanPast(0.0) { (v, _) => if

    (rotate()) v + 1 else v – 0.5 } val viewAngle =
  17. 44 val velocity = ticks.scanPast(0.0) { (v, _) => if

    (rotate()) v + 1 else v – 0.5 } val viewAngle = velocity.scanPast(0.0)(_ + _)
  18. 45

  19. 47 class Matrix { def apply(x: Int, y: Int): Double

    def update(x: Int, y: Int, v: Double) }
  20. 48 val screenMat: Signal[Matrix] = (projMat zip viewMat)(_ * _)

    val invScreenMat = screenMat.map(_.inverse)
  21. 50 val screenMat: Signal[Matrix] = (projMat zip viewMat)(_ * _)

    val invScreenMat = screenMat.map(_.inverse) (4*4*8 + 16 + 16)*4*100 = 64 kb/s
  22. 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) }
  23. 53

  24. 60

  25. 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) } }
  26. 67 val selected = new ReactHashSet[Character] val decorations = selected

    .map(c => (c, decoFor(c))) .react.to[ReactHashMap]
  27. 68 val selected = new ReactHashSet[Character] val decorations = selected

    .map(c => (c, decoFor(c))) .react.to[ReactHashMap]
  28. 69 val selected = new ReactHashSet[Character] val decorations = selected

    .map(c => (c, decoFor(c))) .react.to[ReactHashMap]
  29. 70 val selected = new ReactHashSet[Character] val decorations = selected

    .map(c => (c, decoFor(c))) .react.to[ReactHashMap]
  30. 72 UI isolate class UI extends Isolate[UI.Message] { val frames

    = source.filter(_ == UI.Frame) val exit = source onCase { case UI.Exit => exit() } } Source