monix task · allows fine-grained control over the evaluation model doesn’t trigger any effects...
TRANSCRIPT
![Page 1: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/1.jpg)
MONIX TASKLAZY, ASYNC & AWESOME
Alexandru Nedelcu
Software Developer @ eloquentix.com@alexelcu / alexn.org
![Page 2: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/2.jpg)
MONIX TASK
WHAT IS MONIX?▸ Scala / Scala.js library
▸ For composing asynchronous programs
▸ Exposes Observable & Task
▸ Typelevel Incubator
▸ 2.0-RC2
▸ See: monix.io
![Page 3: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/3.jpg)
EVALUATION
![Page 4: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/4.jpg)
MONIX TASK
EVALUATION IN SCALA
Eager Lazy
A () => A
![Page 5: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/5.jpg)
MONIX TASK
EVALUATION IN SCALA
Eager Lazy
Synchronous A () => A
Asynchronous (A => Unit) => Unit (A => Unit) => Unit
![Page 6: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/6.jpg)
MONIX TASK
EVALUATION IN SCALA
Eager Lazy
Synchronous A () => A
Function0[A]
Asynchronous (A => Unit) => Unit (A => Unit) => Unit
Future[A] Task[A]
![Page 7: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/7.jpg)
“A FUTURE REPRESENTS A VALUE, DETACHED FROM TIME”
Viktor Klang
MONIX TASK
![Page 8: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/8.jpg)
MONIX TASK
TASK FUTURE
import scala.concurrent.ExecutionContextimport ExecutionContext.Implicits.globalimport scala.concurrent.Futureval future = Future { 1 + 1 } // Later ...future.onComplete { case Success(value) => println(v) case Failure(ex) => println(ex.getMessage)}
import monix.execution.Schedulerimport Scheduler.Implicits.globalimport monix.eval.Taskval task = Task { 1 + 1 } // Later ...task.runAsync { case Success(value) => println(v) case Failure(ex) => println(ex.getMessage)}
![Page 9: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/9.jpg)
MONIX TASK
TASK’S BEHAVIOR
▸ allows fine-grained control over the evaluation model
▸ doesn’t trigger any effects until runAsync
▸ doesn’t necessarily execute on another logical thread
▸ allows for cancelling of a running computation
![Page 10: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/10.jpg)
![Page 11: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/11.jpg)
MONIX TASK
EVALUATION
// Strict evaluationTask.now { println("effect"); "immediate" } // Lazy / memoized evaluationTask.evalOnce { println("effect"); "memoized" } // Equivalent to a functionTask.evalAlways { println("effect"); "always" } // Builds a factory of tasks ;-)Task.defer(Task.now { println("effect") })// Guarantees asynchronous executionTask.fork(Task.evalAlways("Hello!"))
![Page 12: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/12.jpg)
MONIX TASK
MEMOIZATION (1/2)
val task1 = Task.evalOnce("effect") val task2 = Task.evalAlways("effect") val task3 = Task.evalAlways("effect").memoize
![Page 13: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/13.jpg)
MONIX TASK
MEMOIZATION (2/2)
task.memoize vs task.runAsync
![Page 14: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/14.jpg)
MONIX TASK
TAIL RECURSIVE LOOPS (1/4)
@tailrecdef fib(cycles: Int, a: BigInt, b: BigInt): BigInt = if (cycles > 0) fib(cycles-1, b, a + b) else b
![Page 15: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/15.jpg)
MONIX TASK
TAIL RECURSIVE LOOPS (2/4)
def fib(cycles: Int, a: BigInt, b: BigInt): Task[BigInt] = if (cycles > 0) Task.defer(fib(cycles-1, b, a+b)) else Task.now(b)
![Page 16: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/16.jpg)
MONIX TASK
TAIL RECURSIVE LOOPS (3/4)
def fib(cycles: Int, a: BigInt, b: BigInt): Task[BigInt] = Task.evalAlways(cycles > 0).flatMap { case true => fib(cycles-1, b, a+b) case false => Task.now(b) }
FlatMap, like all of Task’s operators, is stack-safe ;-)
![Page 17: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/17.jpg)
MONIX TASK
TAIL RECURSIVE LOOPS (4/4)// Mutual Tail Recursion, ftw!!!def odd(n: Int): Task[Boolean] = Task.evalAlways(n == 0).flatMap { case true => Task.now(false) case false => even(n - 1) }def even(n: Int): Task[Boolean] = Task.evalAlways(n == 0).flatMap { case true => Task.now(true) case false => odd(n - 1) }even(1000000)
![Page 18: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/18.jpg)
MONIX TASK
SCHEDULERpackage monix.executiontrait Cancelable { def cancel(): Unit} trait Scheduler extends ExecutionContext { def scheduleOnce(initialDelay: Long, unit: TimeUnit, r: Runnable): Cancelable def currentTimeMillis(): Long def executionModel: ExecutionModel def scheduleWithFixedDelay(...): Cancelable def scheduleAtFixedRate(...): Cancelable}
![Page 19: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/19.jpg)
EXECUTION MODEL
![Page 20: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/20.jpg)
MONIX TASK
▸ in batches, by default
▸ always asynchronous
▸ preferably synchronous
EXECUTION MODEL
![Page 21: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/21.jpg)
MONIX TASK
EXECUTION MODEL: BATCHED
import monix.execution._import monix.execution.schedulers._import ExecutionModel.BatchedExecutionimplicit val scheduler = Scheduler.computation( parallelism=4, executionModel=BatchedExecution(batchSize=1000) )
![Page 22: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/22.jpg)
MONIX TASK
EXECUTION MODEL: ALWAYS ASYNC
import monix.execution._import monix.execution.schedulers._import ExecutionModel.AlwaysAsyncExecutionimplicit val scheduler = Scheduler.computation( parallelism=4, executionModel=AlwaysAsyncExecution )
![Page 23: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/23.jpg)
MONIX TASK
EXECUTION MODEL: PREFER SYNCHRONOUS
import monix.execution._import monix.execution.schedulers._import ExecutionModel.SynchronousExecutionimplicit val scheduler = Scheduler.computation( parallelism=4, executionModel=SynchronousExecution )
![Page 24: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/24.jpg)
REAL ASYNCHRONY
![Page 25: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/25.jpg)
MONIX TASK
REAL ASYNCHRONY
(A => Unit) => Unit
![Page 26: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/26.jpg)
MONIX TASK
REAL ASYNCHRONY
Future[A] => A
![Page 27: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/27.jpg)
MONIX TASK
REAL ASYNCHRONY
Future[A] => A
Always a platform specific hack, just say no to hacks!
![Page 28: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/28.jpg)
MONIX TASK
REAL ASYNCHRONY
def fromFuture[A](future: Future[A]): Task[A] = Task.create { (scheduler, callback) => implicit val ec = scheduler // Waiting ... future.onComplete { case Success(v) => callback.onSuccess(v) case Failure(ex) => callback.onError(ex) } // Futures can't be canceled Cancelable.empty }
![Page 29: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/29.jpg)
MONIX TASK
REAL ASYNCHRONY
// From Future ...val task = Task.defer( Task.fromFuture(Future { "effect" }))// And back again ...val future = task.runAsync// If we want the result ...Await.result(future, 10.seconds)
![Page 30: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/30.jpg)
MONIX TASK
REAL ASYNCHRONY
// From Future ...val task = Task.defer( Task.fromFuture(Future { "effect" }))// And back again ...val future = task.runAsync// If we want the result ...Await.result(future, 10.seconds)
(◕‿◕✿)
![Page 31: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/31.jpg)
![Page 32: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/32.jpg)
CANCELABLESBECAUSE WE SHOULDN’T LEAK
![Page 33: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/33.jpg)
MONIX TASK
CANCELABLESpackage monix.evalsealed abstract class Task[+A] { def runAsync(implicit s: Scheduler): CancelableFuture[A] def runAsync(cb: Callback[A]) (implicit s: Scheduler): Cancelable def runAsync(f: Try[A] => Unit) (implicit s: Scheduler): Cancelable ???}
![Page 34: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/34.jpg)
MONIX TASK
CANCELABLES
// In monix.execution ... trait CancelableFuture[+A] extends Future[A] with Cancelable
val result: CancelableFuture[String] = Task.evalOnce { "result" } .delayExecution(10.seconds) .runAsync// If we change our mind ...result.cancel()
![Page 35: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/35.jpg)
MONIX TASK
CANCELABLES
def delayed[A](timespan: FiniteDuration)(f: => A) = Task.create[A] { (scheduler, callback) => // Register a task in the thread-pool val cancelable = scheduler.scheduleOnce( timespan.length, timespan.unit, new Runnable { def run(): Unit = callback(Try(f)) }) cancelable }
![Page 36: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/36.jpg)
MONIX TASK
CANCELABLES: SAFE FALLBACKS (1/2)
def chooseFirstOf[A,B](fa: Task[A], fb: Task[B]): Task[(A, CancelableFuture[B]) \/ (CancelableFuture[A], B)]
![Page 37: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/37.jpg)
MONIX TASK
CANCELABLES: SAFE FALLBACKS (2/2)
val source: Task[Int] = ???val other: Task[Int] = ???val fallback: Task[Int] = other.delayExecution(5.seconds)Task.chooseFirstOf(source, fallback).map { case Left(((a, futureB))) => futureB.cancel() a case Right((futureA, b)) => futureA.cancel() b}
![Page 38: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/38.jpg)
MONIX TASK
CANCELABLES: BETTER FUTURE.SEQUENCE
val result: Task[Seq[Int]] = Task.zipList(Seq(task1, task2, task3, task4))
On error it does not wait and cancels the unfinished ;-)
![Page 39: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/39.jpg)
MONIX TASK
CANCELABLES: BETTER FUTURE.FIRSTCOMPLETEDOF
val result: Task[Int] = Task.chooseFirstOfList(Seq(task1, task2, task3))
Cancels the unfinished ;-)
![Page 40: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/40.jpg)
MONIX TASK
THE MONAD VERSUS THE APPLICATIVE :-)// Ordered operations ...for { location <- locationTask phone <- phoneTask address <- addressTask} yield { "Gotcha!"} // Potentially in parallelTask.zip3(locationTask, phoneTask, addressTask).map { (location, phone, address) => "Gotcha!"}
![Page 41: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/41.jpg)
MONIX TASK
RESTART, FTW
Task.evalAlways(Random.nextInt()) .restartUntil(_ % 2 == 0)
![Page 42: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/42.jpg)
ERROR HANDLING"If a tree falls in a forest and no one is around to
hear it, does it make a sound?"
![Page 43: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/43.jpg)
MONIX TASK
ERROR HANDLING (1/4)
task.onErrorHandleWith { case _: TimeoutException => fallbackTask case ex => Task.raiseError(ex)}
![Page 44: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/44.jpg)
MONIX TASK
ERROR HANDLING (2/4)
task.onErrorRestart(maxRetries = 20) task.onErrorRestartIf { case _: TimeoutException => true case _ => false}
![Page 45: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/45.jpg)
MONIX TASK
ERROR HANDLING (3/4)
def retryWithBackoff[A](source: Task[A], maxRetries: Int, firstDelay: FiniteDuration): Task[A] = { source.onErrorHandleWith { case ex: Exception => if (maxRetries > 0) retryWithBackoff(source, maxRetries-1, firstDelay*2) .delayExecution(firstDelay) else Task.raiseError(ex) }}
![Page 46: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/46.jpg)
MONIX TASK
ERROR HANDLING (4/4)
task.timeout(10.seconds)task.timeoutTo(10.seconds, Task.raiseError(new TimeoutException()))
![Page 47: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/47.jpg)
IS THAT IT?
![Page 48: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/48.jpg)
MONIX COEVAL
COEVAL▸having the same age or date of origin;
contemporary.
▸ something of the same era
▸ synchronous
![Page 49: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/49.jpg)
MONIX COEVAL
COEVAL▸ like Task, but only for synchronous evaluation
▸ Coeval.now
▸ Coeval.evalOnce
▸ Coeval.evalAlways
▸ coeval.memoize
![Page 50: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/50.jpg)
![Page 51: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/51.jpg)
MONIX COEVAL
COEVAL▸ replacement for by-name parameters
▸ replacement for lazy val
▸ replacement for Function0
▸ stack-safe
![Page 52: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/52.jpg)
MONIX COEVAL
SYNCHRONOUS TAIL RECURSIVE LOOPS :-)import monix.eval.Coevaldef odd(n: Int): Coeval[Boolean] = Coeval.evalAlways(n == 0).flatMap { case true => Coeval.now(false) case false => even(n - 1) }def even(n: Int): Coeval[Boolean] = Coeval.evalAlways(n == 0).flatMap { case true => Coeval.now(true) case false => odd(n - 1) }val result: Boolean = even(1000000).value
![Page 53: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/53.jpg)
MONIX COEVAL
CONVERSION IS EASY
val task: Task[Int] = ???val coeval: Coeval[Either[CancelableFuture[Int], Int]] = task.coeval
![Page 54: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/54.jpg)
MONIX COEVAL
CONVERSION IS EASY
val coeval: Coeval[Int] = ???val task: Task[Int] = coeval.task
![Page 55: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/55.jpg)
MONIX FTW
EVALUATION IN SCALA
Eager Lazy
Synchronous A () => A
Coeval[A]
Asynchronous (A => Unit) => Unit (A => Unit) => Unit
Future[A] Task[A]
![Page 56: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/56.jpg)
MONIX STREAM
STREAMS? (1/4)
sealed abstract class ConsStream[+A] case class Next[A](head: A, tail: ConsStream[A]) extends ConsStream[A] case class Error(ex: Throwable) extends ConsStream[Nothing]case object Empty extends ConsStream[Nothing]
![Page 57: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/57.jpg)
MONIX STREAM
STREAMS? (2/4)
sealed abstract class ConsStream[+A] case class Next[A](head: A, tail: Coeval[ConsStream[A]]) extends ConsStream[A] case class Error(ex: Throwable) extends ConsStream[Nothing]case object Empty extends ConsStream[Nothing]
![Page 58: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/58.jpg)
MONIX STREAM
STREAMS? (3/4)
sealed abstract class ConsStream[+A] case class Next[A](head: A, tail: Task[ConsStream[A]]) extends ConsStream[A] case class Error(ex: Throwable) extends ConsStream[Nothing]case object Empty extends ConsStream[Nothing]
![Page 59: MONIX TASK · allows fine-grained control over the evaluation model doesn’t trigger any effects until runAsync doesn’t necessarily execute on another logical thread allows for](https://reader033.vdocuments.us/reader033/viewer/2022050211/5f5d50e933f7f726bb066302/html5/thumbnails/59.jpg)
MONIX STREAM
STREAMS? (4/4)
import monix.types.Evaluablesealed abstract class ConsStream[+A, F[_] : Evaluable]case class Next[A, F[_] : Evaluable] (head: A, tail: F[ConsStream[A,F]]) extends ConsStream[A,F] case class Error[F[_] : Evaluable](ex: Throwable) extends ConsStream[Nothing,F] case class Empty[F[_] : Evaluable]() extends ConsStream[Nothing,F]