Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Reactive Collections
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Aleksandar Prokopec
July 30, 2014
Programming
0
200
Reactive Collections
Description of the reactive collections framework from the Scala 2014 workshop.
Aleksandar Prokopec
July 30, 2014
Tweet
Share
More Decks by Aleksandar Prokopec
See All by Aleksandar Prokopec
ScalaMeter in 2014
axel22
0
350
A Reactive 3D Game Engine in Scala
axel22
4
8.3k
ScalaBlitz
axel22
0
220
Work-stealing Tree Scheduler
axel22
1
85
ScalaMeter
axel22
0
150
Ctrie Data Structure
axel22
0
240
Parallel Collections Overview
axel22
0
110
Introduction to Scala
axel22
2
310
Other Decks in Programming
See All in Programming
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
190
AI時代の認知負荷との向き合い方
optfit
0
150
組織で育むオブザーバビリティ
ryota_hnk
0
170
AI Agent の開発と運用を支える Durable Execution #AgentsInProd
izumin5210
7
2.3k
Data-Centric Kaggle
isax1015
2
770
AI & Enginnering
codelynx
0
110
360° Signals in Angular: Signal Forms with SignalStore & Resources @ngLondon 01/2026
manfredsteyer
PRO
0
120
AIによる開発の民主化を支える コンテキスト管理のこれまでとこれから
mulyu
3
180
QAフローを最適化し、品質水準を満たしながらリリースまでの期間を最短化する #RSGT2026
shibayu36
2
4.3k
生成AIを使ったコードレビューで定性的に品質カバー
chiilog
1
260
MDN Web Docs に日本語翻訳でコントリビュート
ohmori_yusuke
0
650
HTTPプロトコル正しく理解していますか? 〜かわいい猫と共に学ぼう。ฅ^•ω•^ฅ ニャ〜
hekuchan
2
680
Featured
See All Featured
The Invisible Side of Design
smashingmag
302
51k
Building an army of robots
kneath
306
46k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
[SF Ruby Conf 2025] Rails X
palkan
1
740
Optimizing for Happiness
mojombo
379
71k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
120
Fireside Chat
paigeccino
41
3.8k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
180
The Curious Case for Waylosing
cassininazir
0
230
Designing Experiences People Love
moore
144
24k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.6k
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!