reactive collections

75
1 Containers and Aggregates, Mutators and Isolates for Reactive Programming Aleksandar Prokopec, Philipp Haller, Martin Odersky

Upload: aleksandar-prokopec

Post on 04-Jul-2015

196 views

Category:

Software


0 download

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_BdpLrBVMvkNIMMw

TRANSCRIPT

Page 1: Reactive Collections

1

Containers and Aggregates, Mutators and Isolates

for Reactive Programming

Aleksandar Prokopec, Philipp Haller, Martin Odersky

Page 2: Reactive Collections

Reactive Collections http://reactive-collections.com

2

Page 3: Reactive Collections

Reactive

3

Page 4: Reactive Collections

4

Page 5: Reactive Collections

5

Observables (event streams)

Page 6: Reactive Collections

6

Observables (event streams)

• declarative

val log = messages

.filter(_.length < 100)

.scan(_ + “\n” + _)

Page 7: Reactive Collections

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

}

Page 8: Reactive Collections

8

Actors

• encapsulate mutable state

Page 9: Reactive Collections

9

Actors

• encapsulate mutable state

var log = “”

def receive = {

case s: String =>

if (s.length < 100)

log = log + “\n” + s

}

Page 10: Reactive Collections

10

Reactive collections

Isolate Reactive Channel

Actor ?

ActorRef

? Observable Observable

Page 11: Reactive Collections

11

Reactive values

Page 12: Reactive Collections

Reactive[T]

12

Page 13: Reactive Collections

val ticks: Reactive[Long]

13

ticks 1

1

2

2

3

3

4

4

60

60

61

61

Page 14: Reactive Collections

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

...

Page 15: Reactive Collections

ticks foreach { x => log.debug(s”tick no.$x”) }

15

1 2 3 4 60 61

Page 16: Reactive Collections

16

for (x <- ticks) { log.debug(s”tick no.$x”) }

Single-threaded!

Page 17: Reactive Collections

17

Reactive combinators

Page 18: Reactive Collections

for (x <- ticks) yield { x / 60 }

18

Page 19: Reactive Collections

val seconds: Reactive[Long] = for (x <- ticks) yield { x / 60 }

19

Page 20: Reactive Collections

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

Page 21: Reactive Collections

val days: Reactive[Long] = seconds.map(_ / 86400)

21

Page 22: Reactive Collections

val days: Reactive[Long] = seconds.map(_ / 86400) val secondsToday =

22

Page 23: Reactive Collections

val days: Reactive[Long] = seconds.map(_ / 86400) val secondsToday = (seconds zip days) { (s, d) => s – d * 86400 } 23

Page 24: Reactive Collections

val angle = secondsInDay.map(angleFunc)

24

Page 25: Reactive Collections

val angle = secondsInDay.map(angleFunc) val light = secondsInDay.map(lightFunc)

25

Page 26: Reactive Collections

26

Page 27: Reactive Collections

27

val rotate = keys

a ↓ shift ↓ a ↑ shift ↑ pgup ↓ pgup ↑ keys

Page 28: Reactive Collections

28

val rotate = keys.filter(_ == PAGEUP)

a ↓ shift ↓ a ↑ shift ↑ pgup ↓ pgup ↑ keys

pgup ↓ pgup ↑ filter

Page 29: Reactive Collections

29

val rotate = keys.filter(_ == PAGEUP) .map(_.down)

a ↓ shift ↓ a ↑ shift ↑ pgup ↓ pgup ↑ keys

pgup ↓ pgup ↑ filter

true false map

Page 30: Reactive Collections

30

if (rotate()) viewAngle += 1

true false map

Page 31: Reactive Collections

31

Signals

Page 32: Reactive Collections

32

trait Signal[T] extends Reactive[T] { def apply(): T }

Page 33: Reactive Collections

33

val rotate = keys.filter(_ == PAGEUP) .map(_.down) .signal(false)

true false map

signal

Page 34: Reactive Collections

34

val rotate: Signal[Boolean] = keys.filter(_ == PAGEUP) .map(_.down) .signal(false)

true false map

signal

Page 35: Reactive Collections

35

val rotate: Signal[Boolean] val ticks: Reactive[Long]

ticks

Page 36: Reactive Collections

36

val rotate: Signal[Boolean] val ticks: Reactive[Long]

ticks

rotate

Page 37: Reactive Collections

37

val rotate: Signal[Boolean] val ticks: Reactive[Long] val viewAngle: Signal[Double] =

ticks

rotate

viewAngle

Page 38: Reactive Collections

38

val rotate: Signal[Boolean] val ticks: Reactive[Long] val viewAngle: Signal[Double] = ticks.scanPast(0.0)

ticks

rotate

viewAngle

Page 39: Reactive Collections

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

Page 40: Reactive Collections

40

Page 41: Reactive Collections

41

val velocity = ticks.scanPast(0.0) { (v, _) => } val viewAngle =

Page 42: Reactive Collections

42

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

Page 43: Reactive Collections

43

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

Page 44: Reactive Collections

44

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

Page 45: Reactive Collections

45

Page 46: Reactive Collections

46

Reactive mutators

Page 47: Reactive Collections

47

class Matrix { def apply(x: Int, y: Int): Double def update(x: Int, y: Int, v: Double) }

Page 48: Reactive Collections

48

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

Page 49: Reactive Collections

49

Reactive[immutable.Matrix[T]]

Page 50: Reactive Collections

50

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

(4*4*8 + 16 + 16)*4*100 = 64 kb/s

Page 51: Reactive Collections

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) }

Page 52: Reactive Collections

52

Reactive collections

Page 53: Reactive Collections

53

Page 54: Reactive Collections

54

val selected: Reactive[Set[Character]]

Page 55: Reactive Collections

55

val selected: ReactSet[Character]

Page 56: Reactive Collections

56

trait ReactSet[T] extends ReactContainer[T] { def apply(x: T): Boolean }

Page 57: Reactive Collections

57

trait ReactContainer[T] { def inserts: Reactive[T] def removes: Reactive[T] }

Page 58: Reactive Collections

58

A reactive collection is a pair

of reactive values

Page 59: Reactive Collections

59

val selected = new ReactHashSet[Character]

Page 60: Reactive Collections

60

Page 61: Reactive Collections

61

val selected = new ReactHashSet[Character] val decorations = selected .map(c => (c, decoFor(c)))

Page 62: Reactive Collections

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) } }

Page 63: Reactive Collections

63

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

Page 64: Reactive Collections

64

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

Page 65: Reactive Collections

65

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

Page 66: Reactive Collections

66

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

Page 67: Reactive Collections

67

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

Page 68: Reactive Collections

68

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

Page 69: Reactive Collections

69

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

Page 70: Reactive Collections

70

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

Page 71: Reactive Collections

71

Isolates

Page 72: Reactive Collections

72

UI isolate

class UI extends Isolate[UI.Message] { val frames = source.filter(_ == UI.Frame) val exit = source onCase { case UI.Exit => exit() } }

Source

Page 73: Reactive Collections

73

UI Isolate

Source

AI Isolate

Source

Channel[AI.Message]

Channel[UI.Message]

Page 74: Reactive Collections

74

Reactive collections

Isolate Reactive Channel

Actor ?

ActorRef

? Observable Observable

Page 75: Reactive Collections

75

Thank you!