Reactive Collections

Post on 04-Jul-2015

195 views 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

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!