A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU...
Transcript of A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU...
![Page 1: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/1.jpg)
A TALE OF TWO MONIX STREAMS
Alexandru Nedelcu@alexelcu | alexn.org
![Page 2: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/2.jpg)
MONIX
WHAT IS MONIX?▸ Scala / Scala.js library
▸ For composing asynchronous programs
▸ Exposes Observable, Task, Coeval,Iterant and many concurrency primitives
▸ Typelevel (see typelevel.org)
▸ 3.0.0-M1
▸ See: monix.io
2
![Page 3: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/3.jpg)
3.0▸ Deep integration with Typelevel Cats
▸ Iterant data type for lawful pull-based streaming
▸ major improvements to Observable, Task, Coeval and CancelableFuture
3MONIX
![Page 4: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/4.jpg)
MONIFU▸ Started on January 2, 2014, at 2:30 a.m.
▸ Developed at Eloquentix for monitoring and controlling power plants
▸ Inspired by RxJava / ReactiveX (link)
▸ Renamed to Monix on Dec 30, 2015(issue #91)
▸ Monix comes from: Monads + Rx
4MONIX
![Page 5: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/5.jpg)
MONIFU▸ Started on January 2, 2014, at 2:30 a.m.
▸ Developed at Eloquentix for monitoring and controlling power plants
▸ Inspired by RxJava / ReactiveX (link)
▸ Renamed to Monix on Dec 30, 2015(issue #91)
▸ Monix comes from: Monads + Rx
5MONIX
![Page 6: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/6.jpg)
MONIFU▸ Started on January 2, 2014, at 2:30 a.m.
▸ Developed at Eloquentix for monitoring and controlling power plants
▸ Inspired by RxJava / ReactiveX (link)
▸ Renamed to Monix on Dec 30, 2015(issue #91)
▸ Monix comes from: Monads + Rx
6MONIX
![Page 7: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/7.jpg)
MONIFU▸ Started on January 2, 2014
▸ Developed at Eloquentix for monitoring and controlling power plants
▸ Inspired by RxJava / ReactiveX (link)
▸ Renamed to Monix on Dec 30, 2015(issue #91)
▸ Monix comes from: Monads + Rx
7MONIX
![Page 8: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/8.jpg)
I’M A DEVELOPER, I HAVE NO LIFE
8MONIX
![Page 9: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/9.jpg)
9MONIX
💙+ =
![Page 10: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/10.jpg)
OBSERVABLE[+A]PUSH - BASED STREAMING
![Page 11: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/11.jpg)
MONIX
RX .NET - ORIGINS
▸ Reactive Extensions (also known as ReactiveX)
▸ The Observable pattern
▸ Built at Microsoft by
▸ Jeffery Van Gogh
▸ Wes Dyer
▸ Erik Meijer
▸ Bart De Smet
11
![Page 12: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/12.jpg)
MONIX
RX .NET - ORIGINS
12
trait Iterator[+A] { def hasNext: Boolean def next(): A }
trait Iterable[+A] { def iterator: Iterator[A] }
![Page 13: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/13.jpg)
MONIX
RX .NET - ORIGINS
13
type Iterator[+A] = () !=> Option[Either[Throwable, A]]
type Iterable[+A] = () !=> Iterator[A]
![Page 14: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/14.jpg)
MONIX
RX .NET - ORIGINS
14
type Observer[-A] = Option[Either[Throwable, A]] !=> Unit
type Observable[+A] = Observer[A] !=> Unit
![Page 15: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/15.jpg)
MONIX
RX .NET - ORIGINS
15
trait Observable[+A] { def subscribe(o: Observer[A]): Cancelable }
trait Observer[-A] { def onNext(elem: A): Unit def onComplete(): Unit def onError(e: Throwable): Unit }
![Page 16: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/16.jpg)
MONIX
RX .NET - ORIGINS
16
![Page 17: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/17.jpg)
OBSERVABLE IS THE DUAL OF ITERABLE
Erik Meijer
MONIX 17
![Page 18: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/18.jpg)
18MONIX
▸Pure push - based
▸No protections against slow consumers
▸Unbounded buffers / throttling
▸Trivia: flatMap is aliased to mergeMap because concatMap is unsafe
RX .NET - PROBLEMS
![Page 19: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/19.jpg)
19MONIX
▸Pure push - based
▸No protections against slow consumers
▸Unbounded buffers / throttling
▸Trivia: flatMap is aliased to mergeMap because concatMap is unsafe
RX .NET - PROBLEMS
![Page 20: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/20.jpg)
20MONIX
▸Pure push - based
▸No protections against slow consumers
▸Unbounded buffers / throttling
▸Trivia: flatMap is aliased to mergeMap because concatMap is unsafe
RX .NET - PROBLEMS
![Page 21: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/21.jpg)
MONIX
REACTIVE-STREAMS.ORG
21
trait Subscription { def request(n: Long): Unit def cancel(): Unit }
trait Subscriber[A] { def onSubscribe(s: Subscription): Unit
def onNext(elem: A): Unit def onComplete(): Unit def onError(e: Throwable): Unit }
![Page 22: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/22.jpg)
TOWARD THE FUTURE[A]
![Page 23: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/23.jpg)
MONIX
IDEA 1: BACK-PRESURE WITH FUTURE
23
import scala.concurrent.Future
trait Observer[-A] { def onNext(elem: A): Future[Unit]
def onComplete(): Unit
def onError(e: Throwable): Unit }
![Page 24: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/24.jpg)
MONIX
IDEA 2: CONSUMER DRIVEN CANCELATION
24
sealed trait Ack extends Future[Ack] { !// !!... }
object Ack { /** Signals demand for more. !*/ case object Continue extends Ack
/** Signals demand for early termination. !*/ case object Stop extends Ack }
![Page 25: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/25.jpg)
MONIX
IDEA 2: CONSUMER DRIVEN CANCELATION
25
import monix.execution.Ack import scala.concurrent.Future
trait Observer[-A] { def onNext(elem: A): Future[Ack]
def onComplete(): Unit
def onError(e: Throwable): Unit }
![Page 26: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/26.jpg)
MONIX
SIDE EFFECTS, W00T!26
class SumObserver(take: Int) extends Observer[Int] { private var count = 0 private var sum = 0
def onNext(elem: Int): Ack = { count += 1 sum += elem if (count < take) Continue else { onComplete() Stop } }
def onComplete() = println(s"Sum: $sum") def onError(e: Throwable) = e.printStackTrace() }
![Page 27: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/27.jpg)
MONIX
OBSERVABLE IS HIGH-LEVEL27
val sum: Observable[Long] = Observable.range(0, 1000) .take(100) .map(_ * 2) .foldF
!// Actual execution sum.subscribe(result !=> { println(s"Sum: $result") Stop })
![Page 28: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/28.jpg)
MONIX
val sum: Task[Long] = Observable.range(0, 1000) .take(100) .map(_ * 2) .foldL
!// Actual execution val f: CancelableFuture[Long] = sum.runAsync
OBSERVABLE IS HIGH-LEVEL28
![Page 29: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/29.jpg)
MONIX
val list: Observable[Long] = Observable.range(0, 1000) .take(100) .map(_ * 2)
val consumer: Consumer[Long, Long] = Consumer.foldLeft(0L)(_ + _)
val task: Task[Long] = list.consumeWith(consumer)
OBSERVABLE IS HIGH-LEVEL29
![Page 30: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/30.jpg)
MONIX
def eventsSeq(key: Long): Observable[Long] = ???
observable.flatMap { key !=> eventsSeq(key) }
def someTask(key: Long): Task[Long] = ???
observable.mapTask { key !=> someTask(key) }
def someIO(key: Long): IO[Long] = ???
observable.mapEval { key !=> someIO(key) }
OBSERVABLE IS A MONADIC TYPE30
![Page 31: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/31.jpg)
MONIX
SUSPENDING SIDE EFFECTS31
def readFile(path: String): Observable[String] = Observable.suspend { !// The side effect val lines = Source.fromFile(path).getLines Observable.fromIterator(lines) }
![Page 32: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/32.jpg)
MONIX
SUSPENDING SIDE EFFECTS
▸Does not need IO / Task for evaluation or suspending effects
▸Observable is IO-ish
32
![Page 33: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/33.jpg)
MONIX
observable.mergeMap { key !=> eventsSeq(key) }
observable.switchMap { key !=> eventsSeq(key) }
REACTIVE W00T!33
![Page 34: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/34.jpg)
MONIX
observable.throttleFirst(1.second)
observable.sample(1.second)
observable.debounce(1.second)
observable.echoOnce(1.second)
REACTIVE W00T!34
![Page 35: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/35.jpg)
MONIX
observable.sampleRepeated(1.second)
observable.debounceRepeated(1.second)
observable.echoRepeated(1.second)
REACTIVE W00T!35
![Page 36: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/36.jpg)
MONIX
observable .distinctUntilChanged .sample(1.second) .echoRepeated(5.seconds)
REACTIVE W00T!36
![Page 37: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/37.jpg)
MONIX
observable.publishSelector { hot !=> val a = hot.filter(_ % 2 !== 0).map(_ * 2) val b = hot.filter(_ % 2 !== 1).map(_ * 3) Observable.merge(a, b) }
REACTIVE W00T!37
![Page 38: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/38.jpg)
MONIX
import monix.reactive.OverflowStrategy._
observable.whileBusyBuffer( DropNewAndSignal(1000, count !=> { logger.warn(s"$count events dropped") None }))
observable.asyncBoundary(BackPressure(1000))
REACTIVE W00T!38
![Page 39: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/39.jpg)
MONIX
OBSERVABLE OPTIMISATIONS
▸ Models complex state machine for eliminating asynchronous boundaries
▸ Deals with Concurrency by means of one Atomic
▸ Cache-line padding for avoiding false sharing
▸ Uses getAndSet platform intrinsics
▸ monix-execution ftw
39
FOR FLAT-MAP
![Page 40: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/40.jpg)
MONIX
OBSERVABLE OPTIMISATIONS
▸ Models complex state machine for eliminating asynchronous boundaries
▸ Deals with Concurrency by means of one Atomic
▸ Cache-line padding for avoiding false sharing
▸ Uses getAndSet platform intrinsics
▸ monix-execution ftw
40
FOR FLAT-MAP
![Page 41: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/41.jpg)
MONIX
OBSERVABLE OPTIMISATIONS
▸ Models complex state machine for eliminating asynchronous boundaries
▸ Deals with Concurrency by means of one Atomic
▸ Cache-line padding for avoiding false sharing
▸ Uses getAndSet platform intrinsics
▸ monix-execution ftw
41
FOR FLAT-MAP
![Page 42: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/42.jpg)
MONIX
OBSERVABLE OPTIMISATIONS
▸ Using JCTools.org for non-blocking queues
▸ MPSC scenarios
▸ Consumer does not contend with producers
42
FOR MERGE-MAP / BUFFERING
![Page 43: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/43.jpg)
MONIX
CONSEQUENCES
▸Best in class performance(synchronous ops have ~zero overhead, can optimise synchronous pipelines)
▸Referential Transparency(subscribe <-> unsafePerformIO)
▸ Pure API, Dirty Internals
43
![Page 44: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/44.jpg)
MONIX
CONSEQUENCES
▸Best in class performance(synchronous ops have ~zero overhead, can optimise synchronous pipelines)
▸Referential Transparency (subscribe <-> unsafePerformIO)
▸Pure API, Dirty Internals
44
![Page 45: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/45.jpg)
ITERANT[F,A]PULL-BASED STREAMING
![Page 46: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/46.jpg)
ARCHITECTURE IS FROZEN MUSIC
Johann Wolfgang Von Goethe
ITERANT 46
![Page 47: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/47.jpg)
DATA STRUCTURES ARE FROZEN ALGORITHMS
Jon Bentley
ITERANT 47
![Page 48: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/48.jpg)
48ITERANT
1. Freeze Algorithms into Data-Structures(Immutable)
2. Think State Machines
3. Be Lazy
FP DESIGN - KEY INSIGHTS
![Page 49: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/49.jpg)
49ITERANT
1. Freeze Algorithms into Data-Structures
2. Think State Machines(most of the time)
3. Be Lazy
FP DESIGN - KEY INSIGHTS
![Page 50: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/50.jpg)
50ITERANT
1. Freeze Algorithms into Data-Structures
2. Think State Machines
3. Be Lazy (Strict Values => Functions ;-))
FP DESIGN - KEY INSIGHTS
![Page 51: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/51.jpg)
Finite State Machine Cat
![Page 52: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/52.jpg)
ITERANT
LINKED LISTS
52
sealed trait List[+A]
case class Cons[+A]( head: A, tail: List[A]) extends List[A]
case object Nil extends List[Nothing]
![Page 53: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/53.jpg)
ITERANT
LAZY EVALUATION
53
sealed trait Iterant[A]
case class Next[A]( item: A, rest: () !=> Iterant[A]) extends Iterant[A]
case class Halt[A]( e: Option[Throwable]) extends Iterant[A]
![Page 54: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/54.jpg)
ITERANT
RESOURCE MANAGEMENT
54
sealed trait Iterant[A]
case class Next[A]( item: A, rest: () !=> Iterant[A], stop: () !=> Unit) extends Iterant[A]
case class Halt[A]( e: Option[Throwable]) extends Iterant[A]
![Page 55: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/55.jpg)
ITERANT
DEFERRING
55
sealed trait Iterant[A]
!// !!... case class Suspend[A]( rest: () !=> Iterant[A], stop: () !=> Unit) extends Iterant[A]
![Page 56: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/56.jpg)
ITERANT
FILTER
56
def filter[A](fa: Iterant[A])(p: A !=> Boolean): Iterant[A] = fa match { case halt @ Halt(_) !=> halt !// !!... }
![Page 57: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/57.jpg)
ITERANT
FILTER
57
def filter[A](fa: Iterant[A])(p: A !=> Boolean): Iterant[A] = fa match { !// !!... case Suspend(rest, stop) !=> Suspend(() !=> filter(rest())(p), stop) !// !!... }
![Page 58: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/58.jpg)
ITERANT
FILTER
58
def filter[A](fa: Iterant[A])(p: A !=> Boolean): Iterant[A] = fa match { !// !!... case Next(a, rest, stop) !=> if (p(a)) Next(a, () !=> filter(rest())(p), stop) else Suspend(() !=> filter(rest())(p), stop) }
![Page 59: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/59.jpg)
TRAMPOLINES
![Page 60: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/60.jpg)
ITERANT
CAN WE DO THIS ?
60
case class Next[A]( item: A, rest: Future[Iterant[F, A]], stop: Future[Unit]) extends Iterant[A]
![Page 61: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/61.jpg)
ITERANT
type Task[+A] = () !=> Future[A]
case class Next[A]( item: A, rest: Task[Iterant[F, A]], stop: Task[Unit]) extends Iterant[A]
CAN WE DO THIS ?
61
![Page 62: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/62.jpg)
ITERANT
import monix.eval.Task
case class Next[A]( item: A, rest: Task[Iterant[F, A]], stop: Task[Unit]) extends Iterant[A]
CAN WE DO THIS ?
62
![Page 63: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/63.jpg)
ITERANT
import monix.eval.Coeval
case class Next[A]( item: A, rest: Coeval[Iterant[F, A]], stop: Coeval[Unit]) extends Iterant[A]
CAN WE DO THIS ?
63
![Page 64: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/64.jpg)
ITERANT
import cats.effect.IO
case class Next[A]( item: A, rest: IO[Iterant[F, A]], stop: IO[Unit]) extends Iterant[A]
CAN WE DO THIS ?
64
![Page 65: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/65.jpg)
ITERANT
import cats.Eval
case class Next[A]( item: A, rest: Eval[Iterant[F, A]], stop: Eval[Unit]) extends Iterant[A]
CAN WE DO THIS ?
65
![Page 66: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/66.jpg)
ITERANT
sealed trait Iterant[F[_], A]
case class Next[F[_], A]( item: A, rest: F[Iterant[F, A]], stop: F[Unit]) extends Iterant[F, A]
PARAMETRIC POLYMORPHISM
66
![Page 67: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/67.jpg)
ITERANT
PARAMETRIC POLYMORPHISM
67
import cats.syntax.all._ import cats.effect.Sync def filter[F[_], A](p: A !=> Boolean)(fa: Iterant[F, A]) (implicit F: Sync[F]): Iterant[F, A] = {
fa match { !// !!... case Suspend(rest, stop) !=> Suspend(rest.map(filter(p)), stop) !//!!... } }
![Page 68: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/68.jpg)
ITERANT
BRING YOUR OWN BOOZE
68
import monix.eval.Task
val sum: Task[Int] = Iterant[Task].range(0, 1000) .filter(_ % 2 !== 0) .map(_ * 2) .foldL
![Page 69: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/69.jpg)
ITERANT
BRING YOUR OWN BOOZE
69
import cats.effect.IO
val sum: IO[Int] = Iterant[IO].range(0, 1000) .filter(_ % 2 !== 0) .map(_ * 2) .foldL
![Page 70: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/70.jpg)
ITERANT
BRING YOUR OWN BOOZE
70
import monix.eval.Coeval
val sum: Coeval[Int] = Iterant[Coeval].range(0, 1000) .filter(_ % 2 !== 0) .map(_ * 2) .foldL
![Page 71: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/71.jpg)
ITERANT
PERFORMANCE PROBLEMS
▸Linked Lists are everywhere in FP
▸Linked Lists are terrible
▸Async or Lazy Boundaries are terrible
▸Find Ways to work with Arrays and
▸… to avoid lazy/async boundaries
71
![Page 72: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/72.jpg)
ITERANT
PERFORMANCE SOLUTIONS
▸Linked Lists are everywhere in FP
▸Linked Lists are terrible
▸Async or Lazy Boundaries are terrible
▸Find Ways to work with Arrays and
▸… to avoid lazy/async boundaries
72
![Page 73: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/73.jpg)
ITERANT
WHAT CAN ITERATE OVER ARRAYS?
73
![Page 74: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/74.jpg)
ITERANT
WHAT CAN ITERATE OVER ARRAYS?
74
trait Iterator[+A] { def hasNext: Boolean def next(): A }
trait Iterable[+A] { def iterator: Iterator[A] }
![Page 75: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/75.jpg)
ITERANT
WHAT CAN ITERATE OVER ARRAYS?
75
case class NextBatch[F[_], A]( batch: Iterable[A], rest: F[Iterant[F, A]], stop: F[Unit]) extends Iterant[F, A]
case class NextCursor[F[_], A]( cursor: Iterator[A], rest: F[Iterant[F, A]], stop: F[Unit]) extends Iterant[F, A]
![Page 76: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/76.jpg)
![Page 77: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/77.jpg)
OBSERVABLE[+A]vs
ITERANT[F,A]
![Page 78: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/78.jpg)
OBSERVABLE VS ITERANT
Case Study: scanEval78
https://github.com/monix/monix/pull/412
![Page 79: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/79.jpg)
OBSERVABLE VS ITERANT
Case Study: scanEval79
import cats.effect.Sync
sealed abstract class Iterant[F[_], A] { !// !!... def scanEval[S](seed: F[S])(op: (S, A) !=> F[S]) (implicit F: Sync[F]): Iterant[F, S] = ??? }
![Page 80: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/80.jpg)
OBSERVABLE VS ITERANT
Case Study: scanEval80
def loop(state: S)(source: Iterant[F, A]): Iterant[F, S] = try source match { case Next(head, tail, stop) !=> protectedF(state, head, tail, stop) case ref @ NextCursor(cursor, rest, stop) !=> evalNextCursor(state, ref, cursor, rest, stop) case NextBatch(gen, rest, stop) !=> val cursor = gen.cursor() val ref = NextCursor(cursor, rest, stop) evalNextCursor(state, ref, cursor, rest, stop) case Suspend(rest, stop) !=> Suspend[F,S](rest.map(loop(state)), stop) case Last(item) !=> val fa = ff(state, item) Suspend(fa.map(s !=> lastS[F,S](s)), F.unit) case halt @ Halt(_) !=> halt.asInstanceOf[Iterant[F, S]] } catch { case NonFatal(ex) !=> signalError(source, ex) }
![Page 81: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/81.jpg)
OBSERVABLE VS ITERANT
Case Study: scanEval81
import cats.effect.Effect
abstract class Observable[+A] { !//… def scanEval[F[_], S](seed: F[S])(op: (S, A) !=> F[S]) (implicit F: Effect[F]): Observable[S] = ??? }
![Page 82: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/82.jpg)
OBSERVABLE VS ITERANT
Case Study: scanEval82
abstract class Observable[+A] { !//!!... def scanEval[F[_], S](seed: F[S])(op: (S, A) !=> F[S]) (implicit F: Effect[F]): Observable[S] = scanTask(Task.fromEffect(seed))((a,e) !=> Task.fromEffect(op(a,e)))
def scanTask[S](seed: Task[S])(op: (S, A) !=> Task[S]): Observable[S] = ??? }
![Page 83: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/83.jpg)
OBSERVABLE VS ITERANT
Case Study: scanEval
▸Observable’s scanTask is flatMap
▸With the aforementioned implementation
83
![Page 84: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/84.jpg)
OBSERVABLE VS ITERANT
Benchmark: scanEval84
![Page 85: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/85.jpg)
OBSERVABLE VS ITERANT
Case Study: scanEval
▸Observable has performance
▸ Iterant has reason
85
![Page 86: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/86.jpg)
OBSERVABLE VS ITERANT
Benchmark: map(f).foldL86
![Page 87: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/87.jpg)
OBSERVABLE VS ITERANT
OBSERVABLE FOLD-RIGHT▸ Cannot express foldRight for Observable
▸ But can work with substitutes, e.g. foldWhileLeftL …
87
abstract class Observable[+A] { !// !!... def foldWhileLeftL[S](seed: !=> S) (op: (S, A) !=> Either[S, S]): Task[S] }
![Page 88: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/88.jpg)
OBSERVABLE VS ITERANT
ITERANT FOLD-RIGHT
88
sealed abstract class Iterable[F[_], A] { !// !!... def foldRightL[B](b: F[B]) (f: (A, F[B], F[Unit]) !=> F[B]) (implicit F: Sync[F]): F[B] }
![Page 89: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/89.jpg)
OBSERVABLE VS ITERANT
ITERANT FOLD-RIGHT
89
def exists[F[_], A](ref: Iterant[F, A], p: A !=> Boolean) (implicit F: Sync[F]): F[Boolean] =
ref.foldRightL(F.pure(false)) { (e, next, stop) !=> if (p(e)) stop followedBy F.pure(true) else next }
![Page 90: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/90.jpg)
OBSERVABLE VS ITERANT
ITERANT FOLD-RIGHT
90
def forall[F[_], A](ref: Iterant[F, A], p: A !=> Boolean) (implicit F: Sync[F]): F[Boolean] =
ref.foldRightL(F.pure(true)) { (e, next, stop) !=> if (!p(e)) stop followedBy F.pure(false) else next }
![Page 91: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/91.jpg)
OBSERVABLE VS ITERANT
ITERANT FOLD-RIGHT
91
def concat[F[_], A](lh: Iterant[F, A], rh: Iterant[F, A]) (implicit F: Sync[F]): Iterant[F, A] =
Iterant.suspend[F, A] { lh.foldRightL(F.pure(rh)) { (a, rest, stop) !=> F.pure(Iterant.nextS(a, rest, stop)) } }
![Page 92: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/92.jpg)
OBSERVABLE VS ITERANT
ITERANT FOLD-RIGHT
92
![Page 93: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/93.jpg)
OBSERVABLE VS ITERANT
Conclusions▸Observable is best for
▸Reactive operations
▸Shared data sources
▸Throttling
▸Buffering
▸Performance
▸ Iterant is best for
▸Easier implementation reasoning
▸Converting Task / IO calls into streams
93
![Page 94: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/94.jpg)
OBSERVABLE VS ITERANT
Conclusions▸Both
▸ Implement reactive-streams.org
▸Can express asynchronous streams
▸Do back-pressuring & safe resource handling
94
![Page 95: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/95.jpg)
One more thing …
vs
![Page 96: A TALE OF TWO MONIX STREAMS › public › pdfs › ScalaWorld2017-Tale-TwoStreams.pdf · MONIFU Started on January 2, 2014, at 2:30 a.m. Developed at Eloquentix for monitoring and](https://reader036.fdocuments.in/reader036/viewer/2022070815/5f0eed157e708231d4419e8a/html5/thumbnails/96.jpg)
QUESTIONS?
monix.io
@monix@alexelcu@alexandru
alexn.org@monix