SlideShare a Scribd company logo
Functional Reactive Programming
  with Examples in Scala + GWT

                Sasha Kazachonak
                 kazachonak.com
Google Web Toolkit Tutorial
Scala + GWT. Part 1.
class StockWatcher extends EntryPoint {
   val stocksFlexTable = new FlexTable
   val stocks = new mutable.ArrayBuffer[String]()

  def onModuleLoad {
    stocksFlexTable.setText(0, 0, "Symbol")
    stocksFlexTable.setText(0, 1, "Price")
    stocksFlexTable.setText(0, 2, "Change")
    stocksFlexTable.setText(0, 3, "Remove")
  }
Scala + GWT. Part 2.
private def addStock(symbol: String) {
   if (stocks.contains(symbol))
      return

  val row = stocksFlexTable.getRowCount
  stocks += symbol
  stocksFlexTable.setText(row, 0, symbol)
  stocksFlexTable.setWidget(row, 2, new Label)

  val removeStockButton = new Button("x", new ClickHandler {
     def onClick(event: ClickEvent) = {
       val removedIndex = stocks.indexOf(symbol)
       stocks.remove(removedIndex)
       stocksFlexTable.removeRow(removedIndex + 1)
     }
  })
Scala + GWT. Part 3.
private def updateTable(prices: Array[StockPrice]) {
   prices.foreach(updateTable)
}


private def updateTable(price: StockPrice) {
   if (!stocks.contains(price.symbol)) {
      return
   }

   val row = stocks.indexOf(price.symbol) + 1

   stocksFlexTable.setText(row, 1, price.price)
   val changeWidget = stocksFlexTable.getWidget(row, 2).asInstanceOf
   [Label]
   changeWidget.setText(price.changePercent + "%")
github.com/kazachonak/contour
class StockWatcherView extends View {
   val widget =
      FlexTable(Stock.all)( stock => List(
        Column("Symbol")(Label(stock.symbol)),
        Column("Price")(Label(stock.price.toString)),
        Column("Change")(
           Label(stock.changePercent + "%")
        ),
        Column("Remove")(Button(Stock.all -= stock, "x"))
   ))
    private def addStock(symbol: String) {
      Stock.all += new Stock(symbol)
Good luck doing it in another language

●   No additional variables manipulation
●   Much cooler: FlexTable is not fully re-rendered. Just
    the required rows are updated.
●   Model-View synchronization is incapsulated in
    Reactive Collection implementation and View DSL
    implementation.
●   So it can be reused. No need to synchronize by hand.
●   All those abstractions are fully typesafe
    (indispensable when abstractions are non-trivial)
●   Implemented using only standard Scala language
    features without any magic.
The essence
of functional reactive programming

 is to specify the dynamic behavior of a value
 completely at the time of declaration.

                             Heinrich Apfelmus
                the author of the Haskell library
                               Reactive-banana
The basic ideas
●   Datatypes that represent a value "over time".
●   Computations that involve these changing-
    over-time values will themselves are values
    that change over time.

●   Imagine your program is a spreadsheet and all
    of your variables are cells. If any of the cells in
    a spreadsheet change, any cells that refer to
    that cell change as well.
The basic ideas. Example.
● You could represent the mouse coordinates as a pair of integer-over-time:
    x = mouse.x
    y = mouse.y
● We only need to make this assignment once, and the x and y variables will
  stay "up to date" automatically. No need to mutate variables.
● Computations based on result in values that change over time:
   minX = x – 16
  minY = y – 16
  maxX = x + 16
  maxY = y + 16
   minX will always be 16 less than the x coordinate of the mouse pointer.
● With reactive-aware libraries you could then say something like:
     rectangle(minX, minY, maxX, maxY)
     And a 32x32 box will be drawn around the mouse pointer and will track
   it. wherever it moves.
Deprecating the Observer Pattern
●   By Martin Odersky, Ingo Maier, Tiark Rompf
●   Published in 2010
●   Abstract:
    Programming interactive systems by means of the
    observer pattern is hard and error-prone yet is still
    the implementation standard in many production
    environments.
     We present an approach to gradually deprecate
    observers in favor of reactive programming
    abstractions…
Status quo
●   Growing number of non-expert computer users
●   Increasingly multimedia capable hardware
●   Increasing demand in interactive applications
●   Such apps require much efforts to deal with
    continuous user input and output
●   Programming models for user interfaces have not
    changed much
●   The predominant approach to deal with state
    changes in production software is still the
    observer pattern
Observers => Bugs
●   Quote from Adobe presentation from 2008:
    ●   1/3 of the code in Adobe’s desktop applications is devoted
        to event handling logic
    ●   1/2 of the bugs reported during a product cycle exist in
        this code
●   We claim that we can reduce event handling code by
    at least a factor of 3 once we replace publishers and
    observers with more appropriate abstractions.
●   The same abstractions should help us to reduce the
    bug ratio.
●   We believe that event handling code on average
    should be one of the least error-prone parts of an
    application.
Mouse Dragging Example
var path: Path = null
val moveObserver = { (event: MouseEvent) =>
  path.lineTo(event.position)
  draw(path)
}
control.addMouseDownObserver{ event =>
  path = new Path(event.position)
  control.addMouseMoveObserver(moveObserver)
}
control.addMouseUpObserver{ event =>
  control.removeMouseMoveObserver(moveObserver)
  path.close()
  draw(path)
The observer pattern violates
    many software engineering principles

●   Side-effects
●   Encapsulation
●   Composability
●   Separation of concerns
●   Scalablity
●   Uniformity
●   Abstraction
●   Resource management
●   Semantic distance
Let the tutorial begin
●   reactive-web.co.cc library written in Scala by
    Naftoli Gugenheim
●   I've modified it to make it work when
    compiled to JavaScript by Google Web Toolkit:
     github.com/kazachonak/reactive
EventStream
●   Similar to a collection of values, except that
    rather than all values existing simultaneously,
    each one exists at a different point in time.
●   Methods in reactive-core are named like the
    corresponding methods in the scala
    collections framework.
Creating an EventStream
val eventSource = new EventSource[String] {}
scheduleTask(10000) {
  eventSource.fire("Event after 10 seconds")
}

val eventStream: EventStream[String] =
  eventSource

val widgets =
List(Widgets.EventSourceInput(eventSource),
     Widgets.EventStreamOutput(eventStream))
Timer
class EventStream_Timer extends Demo {
  // Create a timer that fires every 2 seconds,
  // starting at 0, for 30 seconds
  private val timer = new Timer(0, 2000, {t => t
  >= 32000})

  val widgets =
    List(Widgets.EventStreamOutput(timer))
Adding listeners: foreach
val eventSource = new EventSource[String] {}

//The following is syntactic sugar for
// eventSource.foreach(event =>
// Window.alert("You fired: " + event))
for(event <- eventSource) {
   Window.alert("You fired: " + event)
}

val widgets = List(Widgets.EventSourceInput
(eventSource))
EventStream Transformations
●   Similar to how you can transform collections: List
    (1,2,3).map(_ * 10).filter(_ < 25).
●   Consumers of the resulting EventStream don't
    need to care about how it relates to the
    original EventStream.
●   Whenever the original EventStream fires an event,
    the transformed EventStreams may fire their own
    events that are based on the original's event,
    according to the transformation.
A more focused EventStream: filter
 val eventSource = new EventSource[String] {}

 // Only allow short events
 val eventStream =
      eventSource.filter(_.length < 5)

 val widgets =
 List(Widgets.EventSourceInput(eventSource),
    Widgets.EventStreamOutput
 (eventStream))
A transformed EventStream: map
val eventSource = new EventSource[String] {}

// Reverse the event
val eventStream = eventSource.map(_.reverse)

val widgets =
List(Widgets.EventSourceInput(eventSource),
   Widgets.EventStreamOutput(eventStream))
flatMap
  val original = List(1, 2, 3)

  val flatMapped = original.flatMap(x =>
    List(x*10, x*10+1, x*10+2))

  flatMapped ==
     List(10,11,12, 20,21,22, 30,31,32)

Similarly, flatMap allows you to create
  an EventStream that fires events that are fired by
  different other EventStreams.
Combining EventStreams: |
val allClicks = leftClicks | middleClicks | rightClicks
Signal
●   EventStream represents a stream of discrete
    values over time.
    In practice that means that you can never say
    "what is the current value?"
●   Signal represents a continuous value.
    In practical terms, a Signal has a current value,
    and an EventStream that, whenever the
    Signal's value changes, fires the new value.
Signal Examples.
 val myVal = Val(72)
val myVar = Var(31)
myVar.change.foreach(println)
myVar() = 29 // prints 29
Signal. map.
 val myVar = Var(3)
val mapped = myVar.map(_ * 10)
println(mapped.now) // prints 30
myVar() = 62
println(mapped.now) // prints 620
Signal. map.
val myVar = Var("This is a Var")

val mapped =
  myVar.map(s => "Reversed: "+s.reverse)

val widgets =
List(Widgets.VarInput(myVar),
   Widgets.SignalOutput(mapped))
Signal. flatMap.
  val myVar1 = Var(72)
val myVar2 = Var(69)
val myVar3 = Var(false)
val flatMapped = myVar3 flatMap {
   case true => myVar1
   case false => myVar2
}
println(flatMapped.now) // prints 69
myVar3() = true
println(flatMapped.now) // prints 72
myVar2() = 2
myVar1() = 1
println(flatMapped.now) // prints 1
myVar3() = false
Signal. flatMap.
def filteredList(filterSignal: Signal[String],
                   itemsSignal: Signal[List[String]]) =
  for {
     filter <- filterSignal
     items <- itemsSignal
  } yield items.filter(s => s.indexOf(filter) >= 0)
SeqSignal[T] extends Signal[Seq[T]]
 val bufferSignal = BufferSignal(1, 2, 3, 4, 5)

 bufferSignal.value += 6 // fires an Insert

 // fires a Remove and an Insert
 bufferSignal() = List(2, 3, 4, 5, 6, 7)
Stock.all is SeqSignal[Stock]
class StockWatcherView extends View {
   val widget =
      FlexTable(Stock.all)( stock => List(
        Column("Symbol")(Label(stock.symbol)),
        Column("Price")(Label(stock.price.toString)),
        Column("Change")(
           Label(stock.changePercent + "%")
        ),
        Column("Remove")(Button(Stock.all -= stock, "x"))
   ))
    private def addStock(symbol: String) {
      Stock.all += new Stock(symbol)
?

More Related Content

PDF
rx.js make async programming simpler
Alexander Mostovenko
 
PDF
Rxjs kyivjs 2015
Alexander Mostovenko
 
PDF
Qt Animation
William Lee
 
PPTX
Pellucid stm
Dustin Whitney
 
PDF
RxJS - The Reactive extensions for JavaScript
Viliam Elischer
 
PDF
How to become an Android dev starting from iOS (and vice versa)
Giuseppe Filograno
 
PDF
Hash map (java platform se 8 )
charan kumar
 
PPTX
Collection and framework
SARAVANAN GOPALAKRISHNAN
 
rx.js make async programming simpler
Alexander Mostovenko
 
Rxjs kyivjs 2015
Alexander Mostovenko
 
Qt Animation
William Lee
 
Pellucid stm
Dustin Whitney
 
RxJS - The Reactive extensions for JavaScript
Viliam Elischer
 
How to become an Android dev starting from iOS (and vice versa)
Giuseppe Filograno
 
Hash map (java platform se 8 )
charan kumar
 
Collection and framework
SARAVANAN GOPALAKRISHNAN
 

What's hot (20)

PDF
Cascadia.js: Don't Cross the Streams
mattpodwysocki
 
PDF
Reactive data visualisations with Om
Anna Pawlicka
 
PDF
Interaksi obyek
Fajar Baskoro
 
PPT
6.1.1一步一步学repast代码解释
zhang shuren
 
PDF
Petri Niemi Qt Advanced Part 1
NokiaAppForum
 
PDF
Petri Niemi Qt Advanced Part 2
NokiaAppForum
 
PDF
Real World Generics In Swift
Vadym Markov
 
PDF
Mini-lab 1: Stochastic Gradient Descent classifier, Optimizing Logistic Regre...
Yao Yao
 
PDF
Jscex: Write Sexy JavaScript (中文)
jeffz
 
PPT
Functional Programming Past Present Future
IndicThreads
 
PPTX
กลุ่ม6
Witita Khamsook
 
PDF
Map reduce: beyond word count
Jeff Patti
 
PDF
Harnessing the Power of Java 8 Streams
IndicThreads
 
PDF
Practical Model View Programming
Marius Bugge Monsen
 
PDF
Jscex: Write Sexy JavaScript
jeffz
 
PDF
Hw09 Hadoop + Clojure
Cloudera, Inc.
 
PDF
Functional Javascript, CVjs
kaw2
 
PDF
响应式编程及框架
jeffz
 
PPT
Hill ch2ed3
Kunal Verma
 
PDF
Hadoop + Clojure
elliando dias
 
Cascadia.js: Don't Cross the Streams
mattpodwysocki
 
Reactive data visualisations with Om
Anna Pawlicka
 
Interaksi obyek
Fajar Baskoro
 
6.1.1一步一步学repast代码解释
zhang shuren
 
Petri Niemi Qt Advanced Part 1
NokiaAppForum
 
Petri Niemi Qt Advanced Part 2
NokiaAppForum
 
Real World Generics In Swift
Vadym Markov
 
Mini-lab 1: Stochastic Gradient Descent classifier, Optimizing Logistic Regre...
Yao Yao
 
Jscex: Write Sexy JavaScript (中文)
jeffz
 
Functional Programming Past Present Future
IndicThreads
 
กลุ่ม6
Witita Khamsook
 
Map reduce: beyond word count
Jeff Patti
 
Harnessing the Power of Java 8 Streams
IndicThreads
 
Practical Model View Programming
Marius Bugge Monsen
 
Jscex: Write Sexy JavaScript
jeffz
 
Hw09 Hadoop + Clojure
Cloudera, Inc.
 
Functional Javascript, CVjs
kaw2
 
响应式编程及框架
jeffz
 
Hill ch2ed3
Kunal Verma
 
Hadoop + Clojure
elliando dias
 
Ad

Similar to Funtional Reactive Programming with Examples in Scala + GWT (20)

PPS
CS101- Introduction to Computing- Lecture 35
Bilal Ahmed
 
PPTX
Fuel Up JavaScript with Functional Programming
Shine Xavier
 
PPTX
Reactive programming every day
Vadym Khondar
 
PDF
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
GeeksLab Odessa
 
ODP
Functional Programming With Scala
Knoldus Inc.
 
PPTX
Rx workshop
Ryan Riley
 
PPTX
Principles of functional progrmming in scala
ehsoon
 
PPTX
Anais Dotis-Georgiou & Faith Chikwekwe [InfluxData] | Top 10 Hurdles for Flux...
InfluxData
 
ODP
Stratosphere Intro (Java and Scala Interface)
Robert Metzger
 
ODP
Functional programming with Scala
Neelkanth Sachdeva
 
PPTX
Intro to Reactive Thinking and RxJava 2
JollyRogers5
 
PPT
OOADPPT Lecture 5 The OOAD Presentation.pptx
arpit745898
 
PDF
Reactive Programming Patterns with RxSwift
Florent Pillet
 
PDF
This is a C# project . I am expected to create as this image shows. .pdf
indiaartz
 
PDF
Demystifying Reactive Programming
Tom Bulatewicz, PhD
 
PDF
Short intro to scala and the play framework
Felipe
 
PDF
From Java to Scala - advantages and possible risks
SeniorDevOnly
 
PPTX
Intro to Javascript
Anjan Banda
 
PDF
Stata Programming Cheat Sheet
Laura Hughes
 
PPTX
MATLAB Workshop for project and research
Nuthal Srinivasan
 
CS101- Introduction to Computing- Lecture 35
Bilal Ahmed
 
Fuel Up JavaScript with Functional Programming
Shine Xavier
 
Reactive programming every day
Vadym Khondar
 
WebCamp:Front-end Developers Day. Александр Мостовенко "Rx.js - делаем асинхр...
GeeksLab Odessa
 
Functional Programming With Scala
Knoldus Inc.
 
Rx workshop
Ryan Riley
 
Principles of functional progrmming in scala
ehsoon
 
Anais Dotis-Georgiou & Faith Chikwekwe [InfluxData] | Top 10 Hurdles for Flux...
InfluxData
 
Stratosphere Intro (Java and Scala Interface)
Robert Metzger
 
Functional programming with Scala
Neelkanth Sachdeva
 
Intro to Reactive Thinking and RxJava 2
JollyRogers5
 
OOADPPT Lecture 5 The OOAD Presentation.pptx
arpit745898
 
Reactive Programming Patterns with RxSwift
Florent Pillet
 
This is a C# project . I am expected to create as this image shows. .pdf
indiaartz
 
Demystifying Reactive Programming
Tom Bulatewicz, PhD
 
Short intro to scala and the play framework
Felipe
 
From Java to Scala - advantages and possible risks
SeniorDevOnly
 
Intro to Javascript
Anjan Banda
 
Stata Programming Cheat Sheet
Laura Hughes
 
MATLAB Workshop for project and research
Nuthal Srinivasan
 
Ad

More from Vasil Remeniuk (20)

PPTX
Product Minsk - РТБ и Программатик
Vasil Remeniuk
 
PDF
Работа с Akka Сluster, @afiskon, scalaby#14
Vasil Remeniuk
 
PDF
Cake pattern. Presentation by Alex Famin at scalaby#14
Vasil Remeniuk
 
PDF
Scala laboratory: Globus. iteration #3
Vasil Remeniuk
 
PPTX
Testing in Scala by Adform research
Vasil Remeniuk
 
PPTX
Spark Intro by Adform Research
Vasil Remeniuk
 
PPTX
Types by Adform Research, Saulius Valatka
Vasil Remeniuk
 
PPTX
Types by Adform Research
Vasil Remeniuk
 
PPTX
Scalding by Adform Research, Alex Gryzlov
Vasil Remeniuk
 
PPTX
Scalding by Adform Research, Alex Gryzlov
Vasil Remeniuk
 
PPTX
Spark by Adform Research, Paulius
Vasil Remeniuk
 
PPTX
Scala Style by Adform Research (Saulius Valatka)
Vasil Remeniuk
 
PPTX
Spark intro by Adform Research
Vasil Remeniuk
 
PPTX
SBT by Aform Research, Saulius Valatka
Vasil Remeniuk
 
PDF
Scala laboratory: Globus. iteration #2
Vasil Remeniuk
 
PPTX
Testing in Scala. Adform Research
Vasil Remeniuk
 
PDF
Scala laboratory. Globus. iteration #1
Vasil Remeniuk
 
PDF
Cassandra + Spark + Elk
Vasil Remeniuk
 
PDF
Опыт использования Spark, Основано на реальных событиях
Vasil Remeniuk
 
PDF
ETL со Spark
Vasil Remeniuk
 
Product Minsk - РТБ и Программатик
Vasil Remeniuk
 
Работа с Akka Сluster, @afiskon, scalaby#14
Vasil Remeniuk
 
Cake pattern. Presentation by Alex Famin at scalaby#14
Vasil Remeniuk
 
Scala laboratory: Globus. iteration #3
Vasil Remeniuk
 
Testing in Scala by Adform research
Vasil Remeniuk
 
Spark Intro by Adform Research
Vasil Remeniuk
 
Types by Adform Research, Saulius Valatka
Vasil Remeniuk
 
Types by Adform Research
Vasil Remeniuk
 
Scalding by Adform Research, Alex Gryzlov
Vasil Remeniuk
 
Scalding by Adform Research, Alex Gryzlov
Vasil Remeniuk
 
Spark by Adform Research, Paulius
Vasil Remeniuk
 
Scala Style by Adform Research (Saulius Valatka)
Vasil Remeniuk
 
Spark intro by Adform Research
Vasil Remeniuk
 
SBT by Aform Research, Saulius Valatka
Vasil Remeniuk
 
Scala laboratory: Globus. iteration #2
Vasil Remeniuk
 
Testing in Scala. Adform Research
Vasil Remeniuk
 
Scala laboratory. Globus. iteration #1
Vasil Remeniuk
 
Cassandra + Spark + Elk
Vasil Remeniuk
 
Опыт использования Spark, Основано на реальных событиях
Vasil Remeniuk
 
ETL со Spark
Vasil Remeniuk
 

Funtional Reactive Programming with Examples in Scala + GWT

  • 1. Functional Reactive Programming with Examples in Scala + GWT Sasha Kazachonak kazachonak.com
  • 3. Scala + GWT. Part 1. class StockWatcher extends EntryPoint { val stocksFlexTable = new FlexTable val stocks = new mutable.ArrayBuffer[String]() def onModuleLoad { stocksFlexTable.setText(0, 0, "Symbol") stocksFlexTable.setText(0, 1, "Price") stocksFlexTable.setText(0, 2, "Change") stocksFlexTable.setText(0, 3, "Remove") }
  • 4. Scala + GWT. Part 2. private def addStock(symbol: String) { if (stocks.contains(symbol)) return val row = stocksFlexTable.getRowCount stocks += symbol stocksFlexTable.setText(row, 0, symbol) stocksFlexTable.setWidget(row, 2, new Label) val removeStockButton = new Button("x", new ClickHandler { def onClick(event: ClickEvent) = { val removedIndex = stocks.indexOf(symbol) stocks.remove(removedIndex) stocksFlexTable.removeRow(removedIndex + 1) } })
  • 5. Scala + GWT. Part 3. private def updateTable(prices: Array[StockPrice]) { prices.foreach(updateTable) } private def updateTable(price: StockPrice) { if (!stocks.contains(price.symbol)) { return } val row = stocks.indexOf(price.symbol) + 1 stocksFlexTable.setText(row, 1, price.price) val changeWidget = stocksFlexTable.getWidget(row, 2).asInstanceOf [Label] changeWidget.setText(price.changePercent + "%")
  • 6. github.com/kazachonak/contour class StockWatcherView extends View { val widget = FlexTable(Stock.all)( stock => List( Column("Symbol")(Label(stock.symbol)), Column("Price")(Label(stock.price.toString)), Column("Change")( Label(stock.changePercent + "%") ), Column("Remove")(Button(Stock.all -= stock, "x")) )) private def addStock(symbol: String) { Stock.all += new Stock(symbol)
  • 7. Good luck doing it in another language ● No additional variables manipulation ● Much cooler: FlexTable is not fully re-rendered. Just the required rows are updated. ● Model-View synchronization is incapsulated in Reactive Collection implementation and View DSL implementation. ● So it can be reused. No need to synchronize by hand. ● All those abstractions are fully typesafe (indispensable when abstractions are non-trivial) ● Implemented using only standard Scala language features without any magic.
  • 8. The essence of functional reactive programming is to specify the dynamic behavior of a value completely at the time of declaration. Heinrich Apfelmus the author of the Haskell library Reactive-banana
  • 9. The basic ideas ● Datatypes that represent a value "over time". ● Computations that involve these changing- over-time values will themselves are values that change over time. ● Imagine your program is a spreadsheet and all of your variables are cells. If any of the cells in a spreadsheet change, any cells that refer to that cell change as well.
  • 10. The basic ideas. Example. ● You could represent the mouse coordinates as a pair of integer-over-time: x = mouse.x y = mouse.y ● We only need to make this assignment once, and the x and y variables will stay "up to date" automatically. No need to mutate variables. ● Computations based on result in values that change over time: minX = x – 16 minY = y – 16 maxX = x + 16 maxY = y + 16 minX will always be 16 less than the x coordinate of the mouse pointer. ● With reactive-aware libraries you could then say something like: rectangle(minX, minY, maxX, maxY) And a 32x32 box will be drawn around the mouse pointer and will track it. wherever it moves.
  • 11. Deprecating the Observer Pattern ● By Martin Odersky, Ingo Maier, Tiark Rompf ● Published in 2010 ● Abstract: Programming interactive systems by means of the observer pattern is hard and error-prone yet is still the implementation standard in many production environments. We present an approach to gradually deprecate observers in favor of reactive programming abstractions…
  • 12. Status quo ● Growing number of non-expert computer users ● Increasingly multimedia capable hardware ● Increasing demand in interactive applications ● Such apps require much efforts to deal with continuous user input and output ● Programming models for user interfaces have not changed much ● The predominant approach to deal with state changes in production software is still the observer pattern
  • 13. Observers => Bugs ● Quote from Adobe presentation from 2008: ● 1/3 of the code in Adobe’s desktop applications is devoted to event handling logic ● 1/2 of the bugs reported during a product cycle exist in this code ● We claim that we can reduce event handling code by at least a factor of 3 once we replace publishers and observers with more appropriate abstractions. ● The same abstractions should help us to reduce the bug ratio. ● We believe that event handling code on average should be one of the least error-prone parts of an application.
  • 14. Mouse Dragging Example var path: Path = null val moveObserver = { (event: MouseEvent) => path.lineTo(event.position) draw(path) } control.addMouseDownObserver{ event => path = new Path(event.position) control.addMouseMoveObserver(moveObserver) } control.addMouseUpObserver{ event => control.removeMouseMoveObserver(moveObserver) path.close() draw(path)
  • 15. The observer pattern violates many software engineering principles ● Side-effects ● Encapsulation ● Composability ● Separation of concerns ● Scalablity ● Uniformity ● Abstraction ● Resource management ● Semantic distance
  • 16. Let the tutorial begin ● reactive-web.co.cc library written in Scala by Naftoli Gugenheim ● I've modified it to make it work when compiled to JavaScript by Google Web Toolkit: github.com/kazachonak/reactive
  • 17. EventStream ● Similar to a collection of values, except that rather than all values existing simultaneously, each one exists at a different point in time. ● Methods in reactive-core are named like the corresponding methods in the scala collections framework.
  • 18. Creating an EventStream val eventSource = new EventSource[String] {} scheduleTask(10000) { eventSource.fire("Event after 10 seconds") } val eventStream: EventStream[String] = eventSource val widgets = List(Widgets.EventSourceInput(eventSource), Widgets.EventStreamOutput(eventStream))
  • 19. Timer class EventStream_Timer extends Demo { // Create a timer that fires every 2 seconds, // starting at 0, for 30 seconds private val timer = new Timer(0, 2000, {t => t >= 32000}) val widgets = List(Widgets.EventStreamOutput(timer))
  • 20. Adding listeners: foreach val eventSource = new EventSource[String] {} //The following is syntactic sugar for // eventSource.foreach(event => // Window.alert("You fired: " + event)) for(event <- eventSource) { Window.alert("You fired: " + event) } val widgets = List(Widgets.EventSourceInput (eventSource))
  • 21. EventStream Transformations ● Similar to how you can transform collections: List (1,2,3).map(_ * 10).filter(_ < 25). ● Consumers of the resulting EventStream don't need to care about how it relates to the original EventStream. ● Whenever the original EventStream fires an event, the transformed EventStreams may fire their own events that are based on the original's event, according to the transformation.
  • 22. A more focused EventStream: filter val eventSource = new EventSource[String] {} // Only allow short events val eventStream = eventSource.filter(_.length < 5) val widgets = List(Widgets.EventSourceInput(eventSource), Widgets.EventStreamOutput (eventStream))
  • 23. A transformed EventStream: map val eventSource = new EventSource[String] {} // Reverse the event val eventStream = eventSource.map(_.reverse) val widgets = List(Widgets.EventSourceInput(eventSource), Widgets.EventStreamOutput(eventStream))
  • 24. flatMap val original = List(1, 2, 3) val flatMapped = original.flatMap(x => List(x*10, x*10+1, x*10+2)) flatMapped == List(10,11,12, 20,21,22, 30,31,32) Similarly, flatMap allows you to create an EventStream that fires events that are fired by different other EventStreams.
  • 25. Combining EventStreams: | val allClicks = leftClicks | middleClicks | rightClicks
  • 26. Signal ● EventStream represents a stream of discrete values over time. In practice that means that you can never say "what is the current value?" ● Signal represents a continuous value. In practical terms, a Signal has a current value, and an EventStream that, whenever the Signal's value changes, fires the new value.
  • 27. Signal Examples. val myVal = Val(72) val myVar = Var(31) myVar.change.foreach(println) myVar() = 29 // prints 29
  • 28. Signal. map. val myVar = Var(3) val mapped = myVar.map(_ * 10) println(mapped.now) // prints 30 myVar() = 62 println(mapped.now) // prints 620
  • 29. Signal. map. val myVar = Var("This is a Var") val mapped = myVar.map(s => "Reversed: "+s.reverse) val widgets = List(Widgets.VarInput(myVar), Widgets.SignalOutput(mapped))
  • 30. Signal. flatMap. val myVar1 = Var(72) val myVar2 = Var(69) val myVar3 = Var(false) val flatMapped = myVar3 flatMap { case true => myVar1 case false => myVar2 } println(flatMapped.now) // prints 69 myVar3() = true println(flatMapped.now) // prints 72 myVar2() = 2 myVar1() = 1 println(flatMapped.now) // prints 1 myVar3() = false
  • 31. Signal. flatMap. def filteredList(filterSignal: Signal[String], itemsSignal: Signal[List[String]]) = for { filter <- filterSignal items <- itemsSignal } yield items.filter(s => s.indexOf(filter) >= 0)
  • 32. SeqSignal[T] extends Signal[Seq[T]] val bufferSignal = BufferSignal(1, 2, 3, 4, 5) bufferSignal.value += 6 // fires an Insert // fires a Remove and an Insert bufferSignal() = List(2, 3, 4, 5, 6, 7)
  • 33. Stock.all is SeqSignal[Stock] class StockWatcherView extends View { val widget = FlexTable(Stock.all)( stock => List( Column("Symbol")(Label(stock.symbol)), Column("Price")(Label(stock.price.toString)), Column("Change")( Label(stock.changePercent + "%") ), Column("Remove")(Button(Stock.all -= stock, "x")) )) private def addStock(symbol: String) { Stock.all += new Stock(symbol)
  • 34. ?